| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeByteCodePch.h"
- #include "RegexCommon.h"
- #include "RegexPattern.h"
- #include "Library/RegexHelper.h"
- #include "DataStructures/Option.h"
- #include "DataStructures/ImmutableList.h"
- #include "DataStructures/BufferBuilder.h"
- #include "ByteCode/OpCodeUtilAsmJs.h"
- #include "ByteCode/ByteCodeSerializer.h"
- #include "Language/AsmJsModule.h"
- #include "Library/ES5Array.h"
- void ChakraBinaryBuildDateTimeHash(DWORD * buildDateHash, DWORD * buildTimeHash);
- namespace Js
- {
- const int magicConstant = *(int*)"ChBc";
- const int majorVersionConstant = 1;
- const int minorVersionConstant = 1;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- // These magic constants can be enabled to bracket and check different sections of the serialization
- // file. Turn on BYTE_CODE_MAGIC_CONSTANTS in ByteCodeSerializer.h to enable this.
- const int magicStartOfFunctionBody = *(int*)"fun[";
- const int magicEndOfFunctionBody = *(int*)"]fun";
- const int magicStartOfConstantTable = *(int*)"con[";
- const int magicEndOfConstantTable = *(int*)"]con";
- const int magicStartStringConstant = *(int*)"str[";
- const int magicEndStringConstant = *(int*)"]str";
- const int magicStartOfCacheIdToPropIdMap = *(int*)"cid[";
- const int magicEndOfCacheIdToPropIdMap = *(int*)"]cid";
- const int magicStartOfReferencedPropIdMap = *(int*)"rid[";
- const int magicEndOfReferencedPropIdMap = *(int*)"]rid";
- const int magicStartOfPropertyIdsForScopeSlotArray = *(int*)"scp[";
- const int magicEndOfPropertyIdsForScopeSlotArray = *(int*)"]scp";
- const int magicStartOfDebuggerScopes = *(int*)"dsc[";
- const int magicEndOfDebuggerScopes = *(int*)"]dsc";
- const int magicStartOfDebuggerScopeProperties = *(int*)"dsp[";
- const int magicEndOfDebuggerScopeProperties = *(int*)"]dsp";
- const int magicStartOfAux = *(int*)"aux[";
- const int magicEndOfAux = *(int*)"]aux";
- const int magicStartOfAuxVarArray = *(int*)"ava[";
- const int magicEndOfAuxVarArray = *(int*)"]ava";
- const int magicStartOfAuxIntArray = *(int*)"aia[";
- const int magicEndOfAuxIntArray = *(int*)"]aia";
- const int magicStartOfAuxFltArray = *(int*)"afa[";
- const int magicEndOfAuxFltArray = *(int*)"]afa";
- const int magicStartOfAuxPropIdArray = *(int*)"api[";
- const int magicEndOfAuxPropIdArray = *(int*)"]api";
- const int magicStartOfAuxFuncInfoArray = *(int*)"afi[";
- const int magicEndOfAuxFuncInfoArray = *(int*)"]afi";
- const int magicStartOfAsmJsFuncInfo = *(int*)"aFI[";
- const int magicEndOfAsmJsFuncInfo = *(int*)"]aFI";
- const int magicStartOfAsmJsModuleInfo = *(int*)"ami[";
- const int magicEndOfAsmJsModuleInfo = *(int*)"]ami";
- const int magicStartOfPropIdsOfFormals = *(int*)"pif[";
- const int magicEndOfPropIdsOfFormals = *(int*)"]pif";
- const int magicStartOfSlotIdToNestedIndexArray = *(int*)"sni[";
- const int magicEndOfSlotIdToNestedIndexArray = *(int*)"]sni";
- #endif
- // Serialized files are architecture specific
- #ifndef VALIDATE_SERIALIZED_BYTECODE
- #if TARGET_64
- const byte magicArchitecture = 64;
- #else
- const byte magicArchitecture = 32;
- #endif
- #else
- #if _M_AMD64
- const int magicArchitecture = *(int*)"amd";
- #elif _M_IA64
- const int magicArchitecture = *(int*)"ia64";
- #elif _M_ARM
- const int magicArchitecture = *(int*)"arm";
- #elif _M_ARM_64
- const int magicArchitecture = *(int*)"arm64";
- #else
- const int magicArchitecture = *(int*)"x86";
- #endif
- #endif
- // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Byte Code Serializer Versioning scheme
- // 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
- // 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
- // well for QA test runs and buddy tests because there is no chance of effects between runs.
- //
- // 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
- // 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.
- enum FileVersionScheme : byte
- {
- // Currently Chakra and ChakraCore versioning scheme is different.
- // Same version number for Chakra and ChakraCore doesn't mean they are the same.
- // Give the versioning scheme different value, so that byte code generate from one won't be use in the other.
- LibraryByteCodeVersioningScheme = 0,
- #ifdef NTBUILD
- EngineeringVersioningScheme = 10,
- ReleaseVersioningScheme = 20,
- #else
- EngineeringVersioningScheme = 11,
- ReleaseVersioningScheme = 21,
- #endif
- #if (defined(NTBUILD) && CHAKRA_VERSION_RELEASE) || (!defined(NTBUILD) && CHAKRA_CORE_VERSION_RELEASE)
- CurrentFileVersionScheme = ReleaseVersioningScheme
- #else
- CurrentFileVersionScheme = EngineeringVersioningScheme
- #endif
- };
- // it should be in separate file for testing
- #include "ByteCodeCacheReleaseFileVersion.h"
- // Used for selective serialization of Function Body fields to make the representation compact
- #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) bool has_##name : 1
- #define DECLARE_SERIALIZABLE_ACCESSOR_FIELD(type, name, serializableType, defaultValue) bool has_##name : 1
- #define DEFINE_ALL_FIELDS
- struct SerializedFieldList {
- #include "SerializableFunctionFields.h"
- bool has_m_lineNumber: 1;
- bool has_m_columnNumber: 1;
- bool has_attributes : 1;
- bool has_m_nestedCount: 1;
- bool has_loopHeaderArray : 1;
- bool has_asmJsInfo : 1;
- bool has_auxiliary : 1;
- bool has_propertyIdOfFormals: 1;
- bool has_slotIdInCachedScopeToNestedIndexArray : 1;
- bool has_debuggerScopeSlotArray : 1;
- bool has_deferredStubs : 1;
- };
- C_ASSERT(sizeof(GUID)==sizeof(DWORD)*4);
- // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Holds a buffer and size for use by the serializer
- struct ByteBuffer
- {
- uint32 byteCount;
- union
- {
- void * pv;
- const char16 * s16;
- const char * s8;
- };
- public:
- ByteBuffer(uint32 byteCount, void * pv)
- : byteCount(byteCount), pv(pv)
- { }
- };
- } // namespace Js
- template<>
- struct DefaultComparer<Js::ByteBuffer*>
- {
- static bool Equals(Js::ByteBuffer const * str1, Js::ByteBuffer const * str2)
- {
- if (str1->byteCount != str2->byteCount)
- {
- return false;
- }
- return memcmp(str1->pv, str2->pv, str1->byteCount)==0;
- }
- static hash_t GetHashCode(Js::ByteBuffer const * str)
- {
- return JsUtil::CharacterBuffer<char>::StaticGetHashCode(str->s8, str->byteCount);
- }
- };
- namespace Js
- {
- struct IndexEntry
- {
- BufferBuilderByte* isPropertyRecord;
- int id;
- };
- #pragma pack(push, 1)
- struct StringIndexRecord
- {
- int offset;
- bool isPropertyRecord;
- };
- #pragma pack(pop)
- typedef JsUtil::BaseDictionary<ByteBuffer*, IndexEntry, ArenaAllocator, PrimeSizePolicy, DefaultComparer> TString16ToId;
- // Boolean flags on the FunctionBody
- enum FunctionFlags
- {
- ffIsDeclaration = 0x0001,
- ffHasImplicitArgsIn = 0x0002,
- ffIsAccessor = 0x0004,
- ffIsGlobalFunc = 0x0008,
- ffDontInline = 0x0010,
- ffIsFuncRegistered = 0x0020,
- ffIsStaticNameFunction = 0x0040,
- ffIsStrictMode = 0x0080,
- ffDoBackendArgumentsOptimization = 0x0100,
- ffIsEval = 0x0200,
- ffIsDynamicFunction = 0x0400,
- ffhasAllNonLocalReferenced = 0x0800,
- ffhasSetIsObject = 0x1000,
- ffhasSetCallsEval = 0x2000,
- ffIsNameIdentifierRef = 0x4000,
- ffChildCallsEval = 0x8000,
- ffHasReferenceableBuiltInArguments = 0x10000,
- ffIsNamedFunctionExpression = 0x20000,
- ffIsAsmJsMode = 0x40000,
- ffIsAsmJsFunction = 0x80000,
- ffIsAnonymous = 0x100000,
- ffUsesArgumentsObject = 0x200000,
- ffDoScopeObjectCreation = 0x400000,
- ffIsParamAndBodyScopeMerged = 0x800000,
- };
- // Kinds of constant
- enum ConstantType : byte
- {
- ctInt8 = 1,
- ctInt16 = 2,
- ctInt32 = 3,
- ctNumber = 4,
- ctString16 = 5,
- ctPropertyString16 = 6,
- ctNull = 7,
- ctUndefined = 8,
- ctNullDisplay = 9,
- ctStrictNullDisplay = 10,
- ctTrue = 11,
- ctFalse = 12,
- ctStringTemplateCallsite = 13,
- };
- // Try to convert from size_t to uint32. May overflow (and return false) on 64-bit.
- bool TryConvertToUInt32(size_t size, uint32 * out)
- {
- *out = (uint32)size;
- if (sizeof(size) == sizeof(uint32))
- {
- return true;
- }
- Assert(sizeof(size_t) == sizeof(uint64));
- if((uint64)(*out) == size)
- {
- return true;
- }
- AssertMsg(false, "Is it really an offset greater than 32 bits?"); // More likely a bug somewhere.
- return false;
- }
- #if VARIABLE_INT_ENCODING
- template <typename T>
- static const byte * ReadVariableInt(const byte * buffer, size_t remainingBytes, T * value)
- {
- Assert(remainingBytes >= sizeof(byte));
- byte firstByte = *(byte*) buffer;
- if (firstByte >= MIN_SENTINEL)
- {
- Assert(remainingBytes >= sizeof(uint16));
- const byte* locationOfValue = buffer + 1;
- if (firstByte == TWO_BYTE_SENTINEL)
- {
- uint16 twoByteValue = *((serialization_alignment uint16*) locationOfValue);
- Assert(twoByteValue > ONE_BYTE_MAX);
- *value = twoByteValue;
- PHASE_PRINT_TESTTRACE1(Js::VariableIntEncodingPhase, _u("TestTrace: VariableIntEncoding (decode)- 2 bytes, value %u\n"), *value);
- return buffer + sizeof(uint16) +SENTINEL_BYTE_COUNT;
- }
- else
- {
- Assert(remainingBytes >= sizeof(T));
- Assert(firstByte == FOUR_BYTE_SENTINEL);
- *value = *((serialization_alignment T*) locationOfValue);
- Assert(*value > TWO_BYTE_MAX || *value <= 0);
- PHASE_PRINT_TESTTRACE1(Js::VariableIntEncodingPhase, _u("TestTrace: VariableIntEncoding (decode) - 4 bytes, value %u\n"), *value);
- return buffer + sizeof(T) +SENTINEL_BYTE_COUNT;
- }
- }
- else
- {
- *value = (T) firstByte;
- PHASE_PRINT_TESTTRACE1(Js::VariableIntEncodingPhase, _u("TestTrace: VariableIntEncoding (decode) - 1 byte, value %u\n"), *value);
- return buffer + sizeof(byte);
- }
- }
- #endif
- // Compile-time-check some invariants that the file format depends on
- C_ASSERT(sizeof(PropertyId)==sizeof(int32));
- // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Byte Code File Header Layout
- // Offset Size Name Value
- // 0 4 Magic Number "ChBc"
- // 4 4 Total File Size
- // 8 1 File Version Scheme 10 for engineering 20 for release
- // 9 4 Version DWORD 1 jscript minor version GUID quad part 1
- // 13 4 Version DWORD 2 jscript major version GUID quad part 2
- // 17 4 Version DWORD 3 hash of __DATE__ GUID quad part 3
- // 21 4 Version DWORD 4 hash of __TIME__ GUID quad part 4
- // 25 4 Expected Architecture "amd"0, "ia64", "arm"0 or "x86"0
- // 29 4 Expected Function Body Size
- // 33 4 Expected Built In PropertyCount
- // 37 4 Expected Op Code Count
- // 41 4 Size of Original Source Code
- // 45 4 Count of Auxiliary Structures
- // 49 4 Smallest Literal Object ID
- // 53 4 Largest Literal Object ID
- // 57 4 Offset from start of this file
- // to Strings Table
- // 61 4 Offset to Source Spans
- // 65 4 Count of Functions
- // 69 4 Offset to Functions
- // 73 4 Offset to Auxiliary Structures
- // 77 4 Count of Strings
- // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- // This is the serializer
- class ByteCodeBufferBuilder
- {
- // Begin File Layout -------------------------------
- ConstantSizedBufferBuilderOf<int32> magic;
- 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
- BufferBuilderByte fileVersionKind; // Engineering or Release
- ConstantSizedBufferBuilderOf<int32> V1; // V1-V4 are the parts of the version. It is a fixed version GUID or a per-build version.
- ConstantSizedBufferBuilderOf<int32> V2;
- ConstantSizedBufferBuilderOf<int32> V3;
- ConstantSizedBufferBuilderOf<int32> V4;
- BufferBuilderInt32 architecture;
- BufferBuilderInt32 expectedFunctionBodySize;
- BufferBuilderInt32 expectedBuildInPropertyCount;
- BufferBuilderInt32 expectedOpCodeCount;
- BufferBuilderInt32 originalSourceSize;
- BufferBuilderInt32 originalCharLength;
- BufferBuilderRelativeOffset string16sOffset;
- BufferBuilderRelativeOffset lineInfoCacheOffset;
- BufferBuilderRelativeOffset functionsOffset;
- BufferBuilderInt32 string16Count;
- BufferBuilderList string16IndexTable;
- BufferBuilderList string16Table;
- BufferBuilderAligned alignedString16Table;
- BufferBuilderInt32 lineInfoCacheCount;
- BufferBuilderRaw lineCharacterOffsetCacheBuffer;
- BufferBuilderByte lineInfoHasByteCache;
- BufferBuilderRaw lineByteOffsetCacheBuffer;
- BufferBuilderInt32 functionCount;
- BufferBuilderList functionsTable;
- // End File Layout ---------------------------------
- ArenaAllocator * alloc;
- TString16ToId * string16ToId;
- int nextString16Id;
- int topFunctionId;
- LPCUTF8 utf8Source;
- ScriptContext * scriptContext;
- BufferBuilder * startOfCachedScopeAuxBlock;
- DWORD dwFlags;
- //Instead of referencing TotalNumberOfBuiltInProperties directly; or PropertyIds::_countJSOnlyProperty we use this.
- //For library code this will be set to _countJSOnlyProperty and for normal bytecode this will be TotalNumberOfBuiltInProperties
- int builtInPropertyCount;
- bool GenerateLibraryByteCode() const
- {
- return (dwFlags & GENERATE_BYTE_CODE_BUFFER_LIBRARY) != 0;
- }
- bool GenerateByteCodeForNative() const
- {
- return (dwFlags & GENERATE_BYTE_CODE_FOR_NATIVE) != 0;
- }
- bool GenerateParserStateCache() const
- {
- return (dwFlags & GENERATE_BYTE_CODE_PARSER_STATE) != 0;
- }
- public:
- ByteCodeBufferBuilder(uint32 sourceSize, uint32 sourceCharLength, LPCUTF8 utf8Source, Utf8SourceInfo* sourceInfo, ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD dwFlags, int builtInPropertyCount)
- : magic(_u("Magic"), magicConstant),
- totalSize(_u("Total Size"), 0),
- fileVersionKind(_u("FileVersionKind"), 0),
- V1(_u("V1"), 0),
- V2(_u("V2"), 0),
- V3(_u("V3"), 0),
- V4(_u("V4"), 0),
- architecture(_u("Expected Architecture"), magicArchitecture),
- expectedFunctionBodySize(_u("Expected Function Body Size"), sizeof(unaligned FunctionBody)),
- expectedBuildInPropertyCount(_u("Expected Built-in Properties"), builtInPropertyCount),
- expectedOpCodeCount(_u("Expected Number of OpCodes"), (int)OpCode::Count),
- originalSourceSize(_u("Source Size"), sourceSize),
- originalCharLength(_u("Source Char Length"), sourceCharLength),
- string16sOffset(_u("Offset of String16s"), &string16Count),
- lineInfoCacheOffset(_u("Offset of Line Info Cache"), &lineInfoCacheCount),
- functionCount(_u("Function Count"), 0),
- functionsOffset(_u("Offset of Functions"), &functionCount),
- string16Count(_u("String16 Count"), 0),
- string16IndexTable(_u("String16 Indexes")),
- string16Table(_u("String16 Table")),
- alignedString16Table(_u("Alignment for String16 Table"), &string16Table, sizeof(char16)),
- lineInfoCacheCount(_u("Line Info Cache"), sourceInfo->GetLineOffsetCache()->GetLineCount()),
- lineCharacterOffsetCacheBuffer(_u("Line Info Character Cache"), lineInfoCacheCount.value * sizeof(charcount_t), (byte *)sourceInfo->GetLineOffsetCache()->GetLineCharacterOffsetBuffer()),
- lineInfoHasByteCache(_u("Line Info Has Byte Cache"), sourceInfo->GetLineOffsetCache()->GetLineByteOffsetBuffer() != nullptr),
- lineByteOffsetCacheBuffer(_u("Line Info Byte Cache"), lineInfoCacheCount.value * sizeof(charcount_t), (byte *)sourceInfo->GetLineOffsetCache()->GetLineByteOffsetBuffer()),
- functionsTable(_u("Functions")),
- nextString16Id(builtInPropertyCount), // Reserve the built-in property ids
- topFunctionId(0),
- utf8Source(utf8Source),
- scriptContext(scriptContext),
- startOfCachedScopeAuxBlock(nullptr),
- alloc(alloc),
- dwFlags(dwFlags),
- builtInPropertyCount(builtInPropertyCount)
- {
- if (GenerateLibraryByteCode())
- {
- expectedFunctionBodySize.value = 0;
- expectedOpCodeCount.value = 0;
- }
- // Library bytecode uses its own scheme
- byte actualFileVersionScheme = GenerateLibraryByteCode() ? LibraryByteCodeVersioningScheme : CurrentFileVersionScheme;
- #if ENABLE_DEBUG_CONFIG_OPTIONS
- if (Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema)
- {
- actualFileVersionScheme = (byte)Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema;
- }
- #endif
- fileVersionKind.value = actualFileVersionScheme;
- switch (actualFileVersionScheme)
- {
- case EngineeringVersioningScheme:
- {
- Assert(!GenerateLibraryByteCode());
- DWORD jscriptMajor, jscriptMinor, buildDateHash, buildTimeHash;
- Js::VerifyOkCatastrophic(AutoSystemInfo::GetJscriptFileVersion(&jscriptMajor, &jscriptMinor, &buildDateHash, &buildTimeHash));
- V1.value = jscriptMajor;
- V2.value = jscriptMinor;
- V3.value = buildDateHash;
- V4.value = buildTimeHash;
- break;
- }
- case ReleaseVersioningScheme:
- {
- Assert(!GenerateLibraryByteCode());
- auto guidDWORDs = (DWORD*)(&byteCodeCacheReleaseFileVersion);
- V1.value = guidDWORDs[0];
- V2.value = guidDWORDs[1];
- V3.value = guidDWORDs[2];
- V4.value = guidDWORDs[3];
- break;
- }
- case LibraryByteCodeVersioningScheme:
- {
- Assert(GenerateLibraryByteCode());
- // To keep consistent library code between Chakra.dll and ChakraCore.dll, use a fixed version.
- // This goes hand in hand with the bytecode verification unit tests.
- V1.value = 0;
- V2.value = 0;
- V3.value = 0;
- V4.value = 0;
- break;
- }
- default:
- Throw::InternalError();
- break;
- }
- #if ENABLE_DEBUG_CONFIG_OPTIONS
- if (Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion)
- {
- V1.value = Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion;
- V2.value = 0;
- V3.value = 0;
- V4.value = 0;
- }
- #endif
- string16ToId = Anew(alloc, TString16ToId, alloc);
- }
- HRESULT Create(bool allocateBuffer, byte ** buffer, DWORD * bufferBytes)
- {
- BufferBuilderList all(_u("Final"));
- // Reverse the lists
- string16IndexTable.list = string16IndexTable.list->ReverseCurrentList();
- string16Table.list = string16Table.list->ReverseCurrentList();
- // Prepend all sections (in reverse order because of prepend)
- all.list = regex::ImmutableList<Js::BufferBuilder*>::OfSingle(&functionsTable, alloc);
- all.list = all.list->Prepend(&functionCount, alloc);
- if (lineByteOffsetCacheBuffer.raw != nullptr)
- {
- all.list = all.list->Prepend(&lineByteOffsetCacheBuffer, alloc);
- }
- all.list = all.list->Prepend(&lineInfoHasByteCache, alloc);
- all.list = all.list->Prepend(&lineCharacterOffsetCacheBuffer, alloc);
- all.list = all.list->Prepend(&lineInfoCacheCount, alloc);
- all.list = all.list->Prepend(&alignedString16Table, alloc);
- all.list = all.list->Prepend(&string16IndexTable, alloc);
- all.list = all.list->Prepend(&string16Count, alloc);
- all.list = all.list->Prepend(&functionsOffset, alloc);
- all.list = all.list->Prepend(&lineInfoCacheOffset, alloc);
- all.list = all.list->Prepend(&string16sOffset, alloc);
- all.list = all.list->Prepend(&originalCharLength, alloc);
- all.list = all.list->Prepend(&originalSourceSize, alloc);
- all.list = all.list->Prepend(&expectedOpCodeCount, alloc);
- all.list = all.list->Prepend(&expectedBuildInPropertyCount, alloc);
- all.list = all.list->Prepend(&expectedFunctionBodySize, alloc);
- all.list = all.list->Prepend(&architecture, alloc);
- all.list = all.list->Prepend(&V4, alloc);
- all.list = all.list->Prepend(&V3, alloc);
- all.list = all.list->Prepend(&V2, alloc);
- all.list = all.list->Prepend(&V1, alloc);
- all.list = all.list->Prepend(&fileVersionKind, alloc);
- all.list = all.list->Prepend(&totalSize, alloc);
- all.list = all.list->Prepend(&magic, alloc);
- // Get the string count.
- string16Count.value = nextString16Id - this->builtInPropertyCount;
- // Figure out the size and set all individual offsets
- DWORD size = all.FixOffset(0);
- totalSize.value = size;
- // Allocate the bytes
- if (allocateBuffer)
- {
- *bufferBytes = size;
- *buffer = (byte*)CoTaskMemAlloc(*bufferBytes);
- if (*buffer == nullptr)
- {
- return E_OUTOFMEMORY;
- }
- }
- if (size > *bufferBytes)
- {
- *bufferBytes = size;
- return *buffer == nullptr ? S_OK : E_INVALIDARG;
- }
- else
- {
- // Write into the buffer
- all.Write(*buffer, *bufferBytes);
- *bufferBytes = size;
- DebugOnly(Output::Flush()); // Flush trace
- return S_OK;
- }
- }
- bool isBuiltinProperty(PropertyId pid) {
- if (pid < this->builtInPropertyCount || pid==/*nil*/0xffffffff)
- {
- return true;
- }
- return false;
- };
- PropertyId encodeNonBuiltinPropertyId(PropertyId id) {
- const PropertyRecord * propertyValue = nullptr;
- Assert(id >= this->builtInPropertyCount); // Shouldn't have gotten a builtin property id
- propertyValue = scriptContext->GetPropertyName(id);
- id = GetIdOfPropertyRecord(propertyValue) - this->builtInPropertyCount;
- return id ^ SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID;
- };
- PropertyId encodePossiblyBuiltInPropertyId(PropertyId id) {
- const PropertyRecord * propertyValue = nullptr;
- if(id >= this->builtInPropertyCount)
- {
- propertyValue = scriptContext->GetPropertyName(id);
- id = GetIdOfPropertyRecord(propertyValue);
- }
- return id ^ SERIALIZER_OBSCURE_PROPERTY_ID;
- };
- int GetString16Id(ByteBuffer * bb, bool isPropertyRecord = false)
- {
- IndexEntry indexEntry;
- if (!string16ToId->TryGetValue(bb, &indexEntry))
- {
- auto sizeInBytes = bb->byteCount;
- 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
- string16Table.list = string16Table.list->Prepend(stringEntry, alloc);
- if (string16IndexTable.list == nullptr)
- {
- // First item in the list is the first string.
- auto stringIndexEntry = Anew(alloc, BufferBuilderRelativeOffset, _u("First String16 Index"), stringEntry);
- string16IndexTable.list = regex::ImmutableList<Js::BufferBuilder*>::OfSingle(stringIndexEntry, alloc);
- PrependByte(string16IndexTable, _u("isPropertyRecord"), (BYTE)isPropertyRecord);
- }
- // Get a pointer to the previous entry of isPropertyRecord
- indexEntry.isPropertyRecord = static_cast<BufferBuilderByte*>(string16IndexTable.list->First());
- // Subsequent strings indexes point one past the end. This way, the size is always computable by subtracting indexes.
- auto stringIndexEntry = Anew(alloc, BufferBuilderRelativeOffset, _u("String16 Index"), stringEntry, sizeInBytes);
- string16IndexTable.list = string16IndexTable.list->Prepend(stringIndexEntry, alloc);
- // By default, mark the next string to be not a property record.
- PrependByte(string16IndexTable, _u("isPropertyRecord"), (BYTE)false);
- indexEntry.id = nextString16Id;
- string16ToId->Add(bb, indexEntry);
- ++nextString16Id;
- }
- // A string might start off as not being a property record and later becoming one. Hence,
- // we set only if the transition is from false => true. Once it is a property record, it cannot go back.
- if(isPropertyRecord)
- {
- indexEntry.isPropertyRecord->value = isPropertyRecord;
- }
- return indexEntry.id;
- }
- uint32 PrependRelativeOffset(BufferBuilderList & builder, LPCWSTR clue, BufferBuilder * pointedTo)
- {
- auto entry = Anew(alloc, BufferBuilderRelativeOffset, clue, pointedTo, 0);
- builder.list = builder.list->Prepend(entry, alloc);
- return sizeof(int32);
- }
- uint32 PrependInt16(BufferBuilderList & builder, LPCWSTR clue, int16 value, BufferBuilderInt16 ** entryOut = nullptr)
- {
- auto entry = Anew(alloc, BufferBuilderInt16, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- if (entryOut)
- {
- *entryOut = entry;
- }
- return sizeof(int16);
- }
- uint32 PrependInt32(BufferBuilderList & builder, LPCWSTR clue, int value, BufferBuilderInt32 ** entryOut = nullptr)
- {
- auto entry = Anew(alloc, BufferBuilderInt32, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- if (entryOut)
- {
- *entryOut = entry;
- }
- return sizeof(int32);
- }
- uint32 PrependConstantInt16(BufferBuilderList & builder, LPCWSTR clue, int16 value, ConstantSizedBufferBuilderOf<int16> ** entryOut = nullptr)
- {
- auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<int16>, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- if (entryOut)
- {
- *entryOut = entry;
- }
- return sizeof(int16);
- }
- uint32 PrependConstantInt32(BufferBuilderList & builder, LPCWSTR clue, int value, ConstantSizedBufferBuilderOf<int> ** entryOut = nullptr)
- {
- auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<int>, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- if (entryOut)
- {
- *entryOut = entry;
- }
- return sizeof(int32);
- }
- uint32 PrependConstantInt64(BufferBuilderList & builder, LPCWSTR clue, int64 value, ConstantSizedBufferBuilderOf<int64> ** entryOut = nullptr)
- {
- auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<int64>, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- if (entryOut)
- {
- *entryOut = entry;
- }
- return sizeof(int64);
- }
- uint32 PrependByte(BufferBuilderList & builder, LPCWSTR clue, byte value)
- {
- auto entry = Anew(alloc, BufferBuilderByte, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- return sizeof(byte);
- }
- uint32 PrependFunctionBodyFlags(BufferBuilderList & builder, LPCWSTR clue, FunctionBody::FunctionBodyFlags value)
- {
- return PrependByte(builder, clue, (byte) value);
- }
- uint32 PrependBool(BufferBuilderList & builder, LPCWSTR clue, bool value)
- {
- return PrependByte(builder, clue, (byte) value);
- }
- uint32 PrependFloat(BufferBuilderList & builder, LPCWSTR clue, float value)
- {
- auto entry = Anew(alloc, BufferBuilderFloat, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- return sizeof(float);
- }
- uint32 PrependDouble(BufferBuilderList & builder, LPCWSTR clue, double value)
- {
- auto entry = Anew(alloc, BufferBuilderDouble, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- return sizeof(double);
- }
- uint32 PrependSIMDValue(BufferBuilderList & builder, LPCWSTR clue, SIMDValue value)
- {
- auto entry = Anew(alloc, BufferBuilderSIMD, clue, value);
- builder.list = builder.list->Prepend(entry, alloc);
- return sizeof(SIMDValue);
- }
- uint32 PrependString16(__in BufferBuilderList & builder, __in_nz LPCWSTR clue, __in_bcount_opt(byteLength) LPCWSTR sz, __in uint32 byteLength)
- {
- if (sz != nullptr)
- {
- auto bb = Anew(alloc, ByteBuffer, byteLength, (void*)sz); // Includes trailing null
- return PrependInt32(builder, clue, GetString16Id(bb));
- }
- else
- {
- return PrependInt32(builder, clue, 0xffffffff);
- }
- }
- uint32 PrependByteBuffer(BufferBuilderList & builder, LPCWSTR clue, ByteBuffer * bb)
- {
- auto id = GetString16Id(bb);
- return PrependInt32(builder, clue, id);
- }
- int GetIdOfString(__in_bcount_opt(byteLength) LPCWSTR sz, __in uint32 byteLength)
- {
- auto bb = Anew(alloc, ByteBuffer, byteLength, (void*)sz); // Includes trailing null
- return GetString16Id(bb);
- }
- int GetIdOfPropertyRecord(const PropertyRecord * propertyRecord)
- {
- AssertMsg(!propertyRecord->IsSymbol(), "bytecode serializer does not currently handle non-built-in symbol PropertyRecords");
- size_t byteCount = ((size_t)propertyRecord->GetLength() + 1) * sizeof(char16);
- if (byteCount > UINT_MAX)
- {
- // We should never see property record that big
- Js::Throw::InternalError();
- }
- auto buffer = propertyRecord->GetBuffer();
- #if DBG
- const PropertyRecord * propertyRecordCheck;
- scriptContext->FindPropertyRecord(buffer, propertyRecord->GetLength(), &propertyRecordCheck);
- Assert(propertyRecordCheck == propertyRecord);
- #endif
- auto bb = Anew(alloc, ByteBuffer, (uint32)byteCount, (void*)buffer);
- return GetString16Id(bb, /*isPropertyRecord=*/ true);
- }
- template<typename TLayout>
- unaligned TLayout * DuplicateLayout(unaligned const TLayout * in)
- {
- auto sizeOfLayout = sizeof(unaligned TLayout);
- auto newLayout = AnewArray(alloc, byte, sizeOfLayout);
- js_memcpy_s(newLayout, sizeOfLayout, in, sizeOfLayout);
- return (unaligned TLayout * )newLayout;
- }
- template<typename T>
- uint32 Prepend(BufferBuilderList & builder, LPCWSTR clue, T * t)
- {
- auto block = Anew(alloc, BufferBuilderRaw, clue, sizeof(serialization_alignment T), (const byte*)t);
- builder.list = builder.list->Prepend(block, alloc);
- return sizeof(serialization_alignment T);
- }
- struct AuxRecord
- {
- SerializedAuxiliaryKind kind;
- uint offset;
- };
- #ifdef ASMJS_PLAT
- HRESULT RewriteAsmJsByteCodesInto(BufferBuilderList & builder, LPCWSTR clue, FunctionBody * function, ByteBlock * byteBlock, SerializedFieldList& definedFields)
- {
- SListCounted<AuxRecord> auxRecords(alloc);
- auto finalSize = Anew(alloc, BufferBuilderInt32, _u("Final Byte Code Size"), 0); // Initially set to zero
- builder.list = builder.list->Prepend(finalSize, alloc);
- ByteCodeReader reader;
- reader.Create(function);
- uint32 size = 0;
- const byte * opStart = nullptr;
- bool cantGenerate = false;
- auto saveBlock = [&]() {
- uint32 byteCount;
- if (TryConvertToUInt32(reader.GetIP() - opStart, &byteCount))
- {
- if (!GenerateByteCodeForNative())
- {
- auto block = Anew(alloc, BufferBuilderRaw, clue, byteCount, (const byte*)opStart);
- builder.list = builder.list->Prepend(block, alloc);
- size += byteCount;
- }
- }
- else
- {
- AssertMsg(false, "Unlikely: byte code size overflows 32 bits");
- cantGenerate = true;
- }
- };
- Assert(!function->HasCachedScopePropIds());
- while (!cantGenerate)
- {
- opStart = reader.GetIP();
- opStart; // For prefast. It can't figure out that opStart is captured in saveBlock above.
- LayoutSize layoutSize;
- OpCodeAsmJs op = reader.ReadAsmJsOp(layoutSize);
- if (op == OpCodeAsmJs::EndOfBlock)
- {
- saveBlock();
- break;
- }
- OpLayoutTypeAsmJs layoutType = OpCodeUtilAsmJs::GetOpCodeLayout(op);
- switch (layoutType)
- {
- #define LAYOUT_TYPE(layout) \
- case OpLayoutTypeAsmJs::##layout: { \
- Assert(layoutSize == SmallLayout); \
- reader.##layout(); \
- saveBlock(); \
- break; }
- #define LAYOUT_TYPE_WMS(layout) \
- case OpLayoutTypeAsmJs::##layout: { \
- switch (layoutSize) \
- { \
- case SmallLayout: \
- reader.##layout##_Small(); \
- break; \
- case MediumLayout: \
- reader.##layout##_Medium(); \
- break; \
- case LargeLayout: \
- reader.##layout##_Large(); \
- break; \
- default: \
- Assume(UNREACHED); \
- } \
- saveBlock(); \
- break; }
- #include "LayoutTypesAsmJs.h"
- default:
- AssertMsg(false, "Unknown OpLayout");
- cantGenerate = true;
- break;
- }
- }
- if (cantGenerate)
- {
- return ByteCodeSerializer::CantGenerate;
- }
- if (size != byteBlock->GetLength() && !GenerateByteCodeForNative())
- {
- Assert(size == byteBlock->GetLength());
- return ByteCodeSerializer::CantGenerate;
- }
- finalSize->value = size;
- RewriteAuxiliaryInto(builder, auxRecords, reader, function, definedFields);
- return S_OK;
- }
- #endif
- HRESULT RewriteByteCodesInto(BufferBuilderList & builder, LPCWSTR clue, FunctionBody * function, ByteBlock * byteBlock, SerializedFieldList& definedFields)
- {
- SListCounted<AuxRecord> auxRecords(alloc);
- auto finalSize = Anew(alloc, BufferBuilderInt32, _u("Final Byte Code Size"), 0); // Initially set to zero
- builder.list = builder.list->Prepend(finalSize, alloc);
- ByteCodeReader reader;
- reader.Create(function);
- uint32 size = 0;
- const byte * opStart = nullptr;
- bool cantGenerate = false;
- auto saveBlock = [&]() {
- uint32 byteCount;
- if (TryConvertToUInt32(reader.GetIP()-opStart, &byteCount))
- {
- if (!GenerateByteCodeForNative())
- {
- auto block = Anew(alloc, BufferBuilderRaw, clue, byteCount, (const byte*) opStart);
- builder.list = builder.list->Prepend(block, alloc);
- size += byteCount;
- }
- }
- else
- {
- AssertMsg(false, "Unlikely: byte code size overflows 32 bits");
- cantGenerate = true;
- }
- };
- while(!cantGenerate)
- {
- opStart = reader.GetIP();
- opStart; // For prefast. It can't figure out that opStart is captured in saveBlock above.
- LayoutSize layoutSize;
- OpCode op = reader.ReadOp(layoutSize);
- if (op == OpCode::EndOfBlock)
- {
- saveBlock();
- break;
- }
- OpLayoutType layoutType = OpCodeUtil::GetOpCodeLayout(op);
- switch (layoutType)
- {
- #define DEFAULT_LAYOUT(op) \
- case OpLayoutType::##op: { \
- Assert(layoutSize == SmallLayout); \
- reader.##op(); \
- saveBlock(); \
- break; }
- #define DEFAULT_LAYOUT_WITH_ONEBYTE(op) \
- case OpLayoutType::##op: { \
- switch (layoutSize) \
- { \
- case SmallLayout: \
- reader.##op##_Small(); \
- break; \
- case MediumLayout: \
- reader.##op##_Medium(); \
- break; \
- case LargeLayout: \
- reader.##op##_Large(); \
- break; \
- default: \
- Assert(false); \
- __assume(false); \
- } \
- saveBlock(); \
- break; }
- #define DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(op) \
- DEFAULT_LAYOUT_WITH_ONEBYTE(op); \
- DEFAULT_LAYOUT_WITH_ONEBYTE(Profiled##op)
- DEFAULT_LAYOUT(Empty);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg2);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg3);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg4);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg5);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg3C);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Arg);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ArgNoSrc);
- DEFAULT_LAYOUT(Br);
- #ifdef BYTECODE_BRANCH_ISLAND
- DEFAULT_LAYOUT(BrLong);
- #endif
- DEFAULT_LAYOUT(BrS);
- DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg1);
- DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg1Unsigned1);
- DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg2);
- DEFAULT_LAYOUT(StartCall);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Profiled2CallI);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallI);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallIFlags);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallIWithICIndex);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallIFlagsWithICIndex);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementI);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementUnsigned1);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementSlot);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementSlotI1);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementSlotI2);
- DEFAULT_LAYOUT(W1);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg1Unsigned1);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg2Int1);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Unsigned1);
- DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementCP);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementRootCP);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementP);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementPIndexed);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg2B1);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Reg3B1);
- DEFAULT_LAYOUT_WITH_ONEBYTE(Class);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementU);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementRootU);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementScopedC);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementScopedC2);
- DEFAULT_LAYOUT(BrProperty);
- DEFAULT_LAYOUT(BrEnvProperty);
- DEFAULT_LAYOUT(BrLocalProperty);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementC2);
- DEFAULT_LAYOUT_WITH_ONEBYTE(ElementC);
- #undef DEFAULT_LAYOUT
- #undef DEFAULT_LAYOUT_WITH_ONEBYTE
- case OpLayoutType::AuxNoReg:
- switch (op)
- {
- case OpCode::InitCachedFuncs:
- {
- auto layout = reader.AuxNoReg();
- AuxRecord record = { sakFuncInfoArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- default:
- AssertMsg(false, "Unknown OpCode for OpLayoutType::AuxNoReg");
- cantGenerate = true;
- break;
- }
- break;
- case OpLayoutType::Auxiliary:
- switch (op)
- {
- case OpCode::NewScObjectLiteral:
- {
- auto layout = reader.Auxiliary();
- AuxRecord record = { sakPropertyIdArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- case OpCode::LdPropIds:
- {
- auto layout = reader.Auxiliary();
- AuxRecord record = { sakPropertyIdArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- case OpCode::StArrSegItem_A:
- {
- auto layout = reader.Auxiliary();
- AuxRecord record = { sakVarArrayIntCount, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- case OpCode::NewScObject_A:
- {
- auto layout = reader.Auxiliary();
- AuxRecord record = { sakVarArrayVarCount, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- case OpCode::NewScIntArray:
- {
- auto layout = reader.Auxiliary();
- AuxRecord record = { sakIntArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- case OpCode::NewScFltArray:
- {
- auto layout = reader.Auxiliary();
- AuxRecord record = { sakFloatArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- default:
- AssertMsg(false, "Unknown OpCode for OpLayoutType::Auxiliary");
- cantGenerate = true;
- break;
- }
- break;
- case OpLayoutType::ProfiledAuxiliary:
- switch (op)
- {
- case OpCode::ProfiledNewScIntArray:
- {
- auto layout = reader.ProfiledAuxiliary();
- AuxRecord record = { sakIntArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- case OpCode::ProfiledNewScFltArray:
- {
- auto layout = reader.ProfiledAuxiliary();
- AuxRecord record = { sakFloatArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- default:
- AssertMsg(false, "Unknown OpCode for OpLayoutType::ProfiledAuxiliary");
- cantGenerate = true;
- break;
- }
- break;
- case OpLayoutType::Reg2Aux:
- switch (op)
- {
- case OpCode::SpreadArrayLiteral:
- {
- auto layout = reader.Reg2Aux();
- AuxRecord record = { sakIntArray, layout->Offset };
- auxRecords.Prepend(record);
- saveBlock();
- break;
- }
- default:
- AssertMsg(false, "Unknown OpCode for OpLayoutType::Reg2Aux");
- cantGenerate = true;
- break;
- }
- break;
- #define STORE_SPREAD_AUX_ARGS \
- if (!(layout->Options & CallIExtended_SpreadArgs)) \
- { \
- break; \
- } \
- AuxRecord record = { sakIntArray, layout->SpreadAuxOffset }; \
- auxRecords.Prepend(record)
- #define CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(op) \
- case OpLayoutType::##op: \
- { \
- switch (layoutSize) \
- { \
- case SmallLayout: \
- { \
- auto layout = reader.##op##_Small(); \
- STORE_SPREAD_AUX_ARGS; \
- break; \
- } \
- case MediumLayout: \
- { \
- auto layout = reader.##op##_Medium(); \
- STORE_SPREAD_AUX_ARGS; \
- break; \
- } \
- case LargeLayout: \
- { \
- auto layout = reader.##op##_Large(); \
- STORE_SPREAD_AUX_ARGS; \
- break; \
- } \
- default: \
- Assert(false); \
- __assume(false); \
- } \
- saveBlock(); \
- break; \
- }
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(CallIExtended)
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(CallIExtendedFlags)
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtended)
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtendedFlags)
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(Profiled2CallIExtended)
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtendedWithICIndex)
- CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtendedFlagsWithICIndex)
- default:
- AssertMsg(false, "Unknown OpLayout");
- cantGenerate = true;
- break;
- }
- }
- if (cantGenerate)
- {
- return ByteCodeSerializer::CantGenerate;
- }
- if (size != byteBlock->GetLength() && !GenerateByteCodeForNative())
- {
- Assert(size == byteBlock->GetLength());
- return ByteCodeSerializer::CantGenerate;
- }
- finalSize->value = size;
- RewriteAuxiliaryInto(builder, auxRecords, reader, function, definedFields);
- return S_OK;
- }
- void RewriteAuxiliaryInto(BufferBuilderList& builder, SListCounted<AuxRecord> const& auxRecordList,
- ByteCodeReader& reader, FunctionBody * functionBody, SerializedFieldList& definedFields)
- {
- uint count = auxRecordList.Count();
- if (count == 0)
- {
- return;
- }
- definedFields.has_auxiliary = true;
- PrependInt32(builder, _u("Auxiliary Structure Count"), count);
- auto writeAuxVarArray = [&](uint offset, bool isVarCount, int count, const Var * elements) {
- typedef serialization_alignment SerializedVarArray T;
- T header(offset, isVarCount, count);
- auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, _u("Var Array"), header);
- builder.list = builder.list->Prepend(block, alloc);
- for (int i=0;i<count; i++)
- {
- auto var = elements[i];
- PrependVarConstant(builder, var);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Magic end of aux var array"), magicEndOfAuxVarArray);
- PrependInt32(builder, _u("Magic end of aux"), magicEndOfAux);
- #endif
- };
- auto writeAuxVarArrayIntCount = [&](uint offset) {
- const AuxArray<Var> * varArray = reader.ReadAuxArray<Var>(offset, functionBody);
- int count = varArray->count;
- const Var * elements = varArray->elements;
- writeAuxVarArray(offset, false, count, elements);
- };
- auto writeAuxVarArrayVarCount = [&](uint offset) {
- const VarArrayVarCount * varArray = reader.ReadVarArrayVarCount(offset, functionBody);
- int count = Js::TaggedInt::ToInt32(varArray->count);
- const Var * elements = varArray->elements;
- writeAuxVarArray(offset, true, count, elements);
- };
- auto writeAuxIntArray = [&](uint offset) -> BufferBuilder* {
- const AuxArray<int32> *ints = reader.ReadAuxArray<int32>(offset, functionBody);
- int count = ints->count;
- const int32 * elements = ints->elements;
- typedef serialization_alignment SerializedIntArray T;
- T header(offset, count);
- auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, _u("Int Array"), header);
- builder.list = builder.list->Prepend(block, alloc);
- for (int i=0;i<count; i++)
- {
- auto value = elements[i];
- PrependConstantInt32(builder, _u("Integer Constant Value"), value);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Magic end of aux int array"), magicEndOfAuxIntArray);
- PrependInt32(builder, _u("Magic end of aux"), magicEndOfAux);
- #endif
- return block;
- };
- auto writeAuxFloatArray = [&](uint offset) -> BufferBuilder* {
- const AuxArray<double> *doubles = reader.ReadAuxArray<double>(offset, functionBody);
- int count = doubles->count;
- const double * elements = doubles->elements;
- typedef serialization_alignment SerializedFloatArray T;
- T header(offset, count);
- auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, _u("Float Array"), header);
- builder.list = builder.list->Prepend(block, alloc);
- for (int i=0;i<count; i++)
- {
- auto value = elements[i];
- PrependDouble(builder, _u("Number Constant Value"), value);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Magic end of aux float array"), magicEndOfAuxFltArray);
- PrependInt32(builder, _u("Magic end of aux"), magicEndOfAux);
- #endif
- return block;
- };
- auto writeAuxPropertyIdArray = [&](uint offset, byte extraSlots) -> BufferBuilder* {
- const PropertyIdArray * propIds = reader.ReadPropertyIdArray(offset, functionBody);
- typedef serialization_alignment SerializedPropertyIdArray T;
- T header(offset, propIds->count, extraSlots, propIds->hadDuplicates, propIds->has__proto__);
- auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, _u("Property Id Array"), header);
- builder.list = builder.list->Prepend(block, alloc);
- for (uint32 i=0; i<propIds->count; i++)
- {
- auto original = propIds->elements[i];
- auto encoded = encodePossiblyBuiltInPropertyId(original);
- PrependConstantInt32(builder, _u("Encoded Property Id"), encoded);
- }
- auto slots = propIds->elements + propIds->count;
- for(byte i=0; i<extraSlots; i++)
- {
- PrependConstantInt32(builder, _u("Extra Slot"), slots[i]);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Magic end of aux section"), magicEndOfAuxPropIdArray);
- PrependInt32(builder, _u("Magic end of aux"), magicEndOfAux);
- #endif
- return block;
- };
- auto writeAuxFuncInfoArray = [&](uint offset) -> BufferBuilder* {
- const FuncInfoArray * funcInfos = reader.ReadAuxArray<FuncInfoEntry>(offset, functionBody);
- typedef serialization_alignment SerializedFuncInfoArray T;
- T header(offset, funcInfos->count);
- auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, _u("Funcinfo Array"), header);
- builder.list = builder.list->Prepend(block, alloc);
- for (uint32 i=0; i<funcInfos->count; i++)
- {
- auto funcInfo = funcInfos->elements[i];
- PrependConstantInt32(builder, _u("FuncInfo nestedIndex"), funcInfo.nestedIndex);
- PrependConstantInt32(builder, _u("FuncInfo scopeSlot"), funcInfo.scopeSlot);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Magic end of aux section"), magicEndOfAuxFuncInfoArray);
- PrependInt32(builder, _u("Magic end of aux"), magicEndOfAux);
- #endif
- return block;
- };
- PrependInt32(builder, _u("Auxiliary Size"),
- functionBody->GetAuxiliaryData()? functionBody->GetAuxiliaryData()->GetLength() : 0);
- PrependInt32(builder, _u("Auxiliary Context Size"),
- functionBody->GetAuxiliaryContextData()? functionBody->GetAuxiliaryContextData()->GetLength() : 0);
- auxRecordList.Map([&](AuxRecord const& auxRecord)
- {
- switch (auxRecord.kind)
- {
- default:
- AssertMsg(false, "Unexpected auxiliary kind");
- Throw::FatalInternalError();
- break;
- case sakVarArrayIntCount:
- writeAuxVarArrayIntCount(auxRecord.offset);
- break;
- case sakVarArrayVarCount:
- writeAuxVarArrayVarCount(auxRecord.offset);
- break;
- case sakIntArray:
- writeAuxIntArray(auxRecord.offset);
- break;
- case sakFloatArray:
- writeAuxFloatArray(auxRecord.offset);
- break;
- case sakPropertyIdArray:
- writeAuxPropertyIdArray(auxRecord.offset, 0);
- break;
- case sakFuncInfoArray:
- writeAuxFuncInfoArray(auxRecord.offset);
- break;
- };
- });
- }
- uint32 PrependStringConstant(BufferBuilderList & builder, Var var)
- {
- auto str = JavascriptString::FromVar(var);
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start String Constant"), magicStartStringConstant);
- #endif
- auto bb = Anew(alloc, ByteBuffer, (str->GetLength() + 1) * sizeof(char16), (void*)str->GetSz());
- size += PrependByteBuffer(builder, _u("String Constant 16 Value"), bb);
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End String Constant"), magicEndStringConstant);
- #endif
- return size;
- }
- uint32 PrependStringTemplateCallsiteConstant(BufferBuilderList & builder, Var var)
- {
- ES5Array* callsite = ES5Array::FromVar(var);
- Var element = nullptr;
- auto size = PrependInt32(builder, _u("String Template Callsite Constant String Count"), (int)callsite->GetLength());
- for (uint32 i = 0; i < callsite->GetLength(); i++)
- {
- callsite->DirectGetItemAt(i, &element);
- size += PrependStringConstant(builder, element);
- }
- Var rawVar = JavascriptOperators::OP_GetProperty(callsite, Js::PropertyIds::raw, callsite->GetScriptContext());
- ES5Array* rawArray = ES5Array::FromVar(rawVar);
- for (uint32 i = 0; i < rawArray->GetLength(); i++)
- {
- rawArray->DirectGetItemAt(i, &element);
- size += PrependStringConstant(builder, element);
- }
- return size;
- }
- uint32 PrependVarConstant(BufferBuilderList & builder, Var var)
- {
- if (var == (Js::Var)&Js::NullFrameDisplay)
- {
- return PrependByte(builder, _u("Null Frame Display"), ctNullDisplay);
- }
- else if (var == (Js::Var)&Js::StrictNullFrameDisplay)
- {
- return PrependByte(builder, _u("Strict Null Frame Display"), ctStrictNullDisplay);
- }
- auto typeId = JavascriptOperators::GetTypeId(var);
- switch (typeId)
- {
- case TypeIds_Undefined:
- return PrependByte(builder, _u("Undefined Constant"), ctUndefined);
- case TypeIds_Null:
- return PrependByte(builder, _u("Null Constant"), ctNull);
- case TypeIds_Boolean:
- return PrependByte(builder, _u("Boolean Constant"), JavascriptBoolean::FromVar(var)->GetValue()? ctTrue : ctFalse);
- case TypeIds_Number:
- {
- auto size = PrependByte(builder, _u("Number Constant"), ctNumber);
- return size + PrependDouble(builder, _u("Number Constant Value"), JavascriptNumber::GetValue(var));
- }
- case TypeIds_Integer:
- {
- int32 value = TaggedInt::ToInt32(var);
- if ((int8)value == value)
- {
- auto size = PrependByte(builder, _u("Integer Constant"), ctInt8);
- return size + PrependByte(builder, _u("Integer Constant Value"), (byte)value);
- }
- else if ((int16)value == value)
- {
- auto size = PrependByte(builder, _u("Integer Constant"), ctInt16);
- return size + PrependConstantInt16(builder, _u("Integer Constant Value"), (int16)value);
- }
- else
- {
- auto size = PrependByte(builder, _u("Integer Constant"), ctInt32);
- return size + PrependConstantInt32(builder, _u("Integer Constant Value"), value);
- }
- }
- case TypeIds_String:
- {
- auto size = PrependByte(builder, _u("String Constant 16"),
- Js::PropertyString::Is(var)? ctPropertyString16 : ctString16);
- return size + PrependStringConstant(builder, var);
- }
- case TypeIds_ES5Array:
- {
- // ES5Array objects in the constant table are always string template callsite objects.
- // If we later put other ES5Array objects in the constant table, we'll need another way
- // to decide the constant type.
- auto size = PrependByte(builder, _u("String Template Callsite Constant"), ctStringTemplateCallsite);
- return size + PrependStringTemplateCallsiteConstant(builder, var);
- }
- default:
- AssertMsg(UNREACHED, "Unexpected object type in AddConstantTable");
- Throw::FatalInternalError();
- }
- }
- #ifdef ASMJS_PLAT
- uint32 AddAsmJsConstantTable(BufferBuilderList & builder, FunctionBody * function)
- {
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start Constant Table"), magicStartOfConstantTable);
- #endif
- auto constTable = function->GetConstTable();
- byte* tableEnd = (byte*)(constTable + function->GetConstantCount());
- for (int i = 0; i < WAsmJs::LIMIT; ++i)
- {
- WAsmJs::Types type = (WAsmJs::Types)i;
- WAsmJs::TypedSlotInfo* typedInfo = function->GetAsmJsFunctionInfo()->GetTypedSlotInfo(type);
- uint32 constCount = typedInfo->constCount;
- if (constCount > FunctionBody::FirstRegSlot)
- {
- uint32 typeSize = WAsmJs::GetTypeByteSize(type);
- byte* byteTable = ((byte*)constTable) + typedInfo->constSrcByteOffset;
- byteTable += typeSize * FunctionBody::FirstRegSlot;
- for (uint32 reg = FunctionBody::FirstRegSlot; reg < constCount; ++reg)
- {
- switch (type)
- {
- case WAsmJs::INT32: PrependConstantInt32(builder, _u("Integer Constant Value"), *(int*)byteTable); break;
- case WAsmJs::FLOAT32: PrependFloat(builder, _u("Float Constant Value"), *(float*)byteTable); break;
- case WAsmJs::FLOAT64: PrependDouble(builder, _u("Double Constant Value"), *(double*)byteTable); break;
- default:
- Assert(UNREACHED);
- Js::Throw::FatalInternalError();
- break;
- }
- byteTable += typeSize;
- }
- if (byteTable > tableEnd)
- {
- Assert(UNREACHED);
- Js::Throw::FatalInternalError();
- }
- }
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End Constant Table"), magicEndOfConstantTable);
- #endif
- return size;
- }
- #endif
- uint32 AddConstantTable(BufferBuilderList & builder, FunctionBody * function)
- {
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start Constant Table"), magicStartOfConstantTable);
- #endif
- for (auto reg = FunctionBody::FirstRegSlot + 1; reg < function->GetConstantCount(); reg++) // Ignore first slot, it is always global object or module root object
- {
- auto var = function->GetConstantVar(reg);
- Assert(var != nullptr);
- size += PrependVarConstant(builder, var);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End Constant Table"), magicEndOfConstantTable);
- #endif
- return size;
- }
- uint32 AddPropertyIdsForScopeSlotArray(BufferBuilderList & builder, FunctionBody * function)
- {
- if (function->scopeSlotArraySize == 0)
- {
- return 0;
- }
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start PropertyIdsForScopeSlotsArray"), magicStartOfPropertyIdsForScopeSlotArray);
- #endif
- for (uint i = 0; i < function->scopeSlotArraySize; i++)
- {
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(function->GetPropertyIdsForScopeSlotArray()[i]);
- size += PrependInt32(builder, _u("PropertyIdsForScopeSlots"), propertyId);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End PropertyIdsForScopeSlotsArray"), magicEndOfPropertyIdsForScopeSlotArray);
- #endif
- return size;
- }
- uint32 AddSlotIdInCachedScopeToNestedIndexArray(BufferBuilderList& builder, FunctionBody * functionBody)
- {
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start SlotIdInCachedScopeToNestedIndexArray"), magicStartOfSlotIdToNestedIndexArray);
- #endif
- Js::AuxArray<uint32> * slotIdToNestedIndexArray = functionBody->GetSlotIdInCachedScopeToNestedIndexArray();
- size += PrependInt32(builder, _u("SlotIdInCachedScopeToNestedIndexArray count"), slotIdToNestedIndexArray->count);
- for (uint i = 0; i < slotIdToNestedIndexArray->count; i++)
- {
- size += PrependInt32(builder, _u("Nested function index for slot id in cached scope"), slotIdToNestedIndexArray->elements[i]);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End magicStartOfSlotIdToNestedIndexArray"), magicEndOfSlotIdToNestedIndexArray);
- #endif
- return size;
- }
- // Gets the number of debugger slot array scopes there are in the function body's scope chain list.
- uint32 GetDebuggerScopeSlotArrayCount(FunctionBody * function)
- {
- Assert(function);
- uint debuggerScopeSlotArraySize = 0;
- if (function->GetScopeObjectChain())
- {
- debuggerScopeSlotArraySize = function->GetScopeObjectChain()->pScopeChain->CountWhere([&](DebuggerScope* scope)
- {
- return scope->IsSlotScope();
- });
- }
- return debuggerScopeSlotArraySize;
- }
- // Adds the debugger scopes that are slot array type to the serialized bytecode.
- // This is to ensure that block scope slot array properties are captured along with
- // function level slot array properties.
- uint32 AddSlotArrayDebuggerScopeProperties(BufferBuilderList & builder, DebuggerScope* debuggerScope, uint propertiesCount)
- {
- Assert(debuggerScope);
- if (propertiesCount == 0)
- {
- return 0u;
- }
- uint32 size = 0u;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start SlotArrayDebuggerScopeProperties"), magicStartOfDebuggerScopeProperties);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- AssertMsg(debuggerScope->HasProperties(), "Properties should exist.");
- Assert(debuggerScope->scopeProperties->Count() >= 0);
- AssertMsg((uint)debuggerScope->scopeProperties->Count() == propertiesCount, "Property counts should match.");
- for (uint i = 0u; i < propertiesCount; ++i)
- {
- DebuggerScopeProperty scopeProperty = debuggerScope->scopeProperties->Item(i);
- size += PrependInt32(builder, _u("SlotIndexesForDebuggerScopeSlots"), scopeProperty.location);
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(scopeProperty.propId);
- size += PrependInt32(builder, _u("PropertyIdsForDebuggerScopeSlots"), propertyId);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End SlotArrayDebuggerScopeProperties"), magicEndOfDebuggerScopeProperties);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- return size;
- }
- // Adds the debugger scopes that are slot array type to the serialized bytecode.
- // This is to ensure that block scope slot array properties are captured along with
- // function level slot array properties.
- uint32 AddSlotArrayDebuggerScopes(BufferBuilderList & builder, FunctionBody* function, uint debuggerScopeSlotArraySize)
- {
- Assert(function);
- if (function->GetScopeObjectChain() == nullptr || debuggerScopeSlotArraySize == 0)
- {
- return 0u;
- }
- uint32 size = 0u;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start SlotArrayDebuggerScopes"), magicStartOfDebuggerScopes);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- uint slotArrayCount = 0;
- for (uint i = 0u; i < static_cast<uint>(function->GetScopeObjectChain()->pScopeChain->Count()); ++i)
- {
- DebuggerScope* debuggerScope = function->GetScopeObjectChain()->pScopeChain->Item(i);
- if (debuggerScope->IsSlotScope())
- {
- // Only add slot scope debugger scopes (store the index of the scope).
- size += PrependInt32(builder, _u("SlotArrayDebuggerScope"), i);
- // Store the count of properties for the scope.
- int propertiesCount = debuggerScope->HasProperties() ? debuggerScope->scopeProperties->Count() : 0u;
- size += PrependInt32(builder, _u("Debugger Scope Slot Array Property Count"), propertiesCount);
- size += AddSlotArrayDebuggerScopeProperties(builder, debuggerScope, propertiesCount);
- slotArrayCount++;
- }
- }
- Assert(debuggerScopeSlotArraySize == slotArrayCount);
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End SlotArrayDebuggerScopes"), magicEndOfDebuggerScopes);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- return size;
- }
- uint32 AddCacheIdToPropertyIdMap(BufferBuilderList & builder, FunctionBody * function)
- {
- uint count = function->GetInlineCacheCount();
- if (count == 0)
- {
- return 0;
- }
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Start CacheId-to-PropertyId map"), magicStartOfCacheIdToPropIdMap);
- #endif
- for (uint i = 0; i < count; i++)
- {
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(function->GetPropertyIdFromCacheId(i));
- size += PrependInt32(builder, _u("CacheIdToPropertyId"), propertyId);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End CacheId-to-PropertyId map"), magicEndOfCacheIdToPropIdMap);
- #endif
- return size;
- }
- uint32 AddReferencedPropertyIdMap(BufferBuilderList & builder, FunctionBody * function)
- {
- uint count = function->GetReferencedPropertyIdCount();
- if (count == 0)
- {
- return 0;
- }
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Start Referenced-PropertyId map"), magicStartOfReferencedPropIdMap);
- #endif
- for (uint i = 0; i < count; i++)
- {
- PropertyId propertyId = encodeNonBuiltinPropertyId(function->GetReferencedPropertyIdWithMapIndex(i));
- size += PrependInt32(builder, _u("ReferencedPropertyId"), propertyId);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End Referenced-PropertyId map"), magicEndOfReferencedPropIdMap);
- #endif
- return size;
- }
- uint32 PrependByteArray(BufferBuilderList & builder, int length, byte * buffer)
- {
- int size = 0;
- for (int i = 0; i<length; ++i)
- {
- size += PrependByte(builder, _u("Byte Array Element"), buffer[i]);
- }
- return size;
- }
- uint32 PrependUInt32Array(BufferBuilderList & builder, int length, uint32 * buffer)
- {
- int size = 0;
- for(int i=0;i<length;++i)
- {
- size += PrependConstantInt32(builder, _u("UInt32 Array Element"), buffer[i]);
- }
- return size;
- }
- uint32 PrependGrowingUint32Array(BufferBuilderList & builder, LPCWSTR clue, JsUtil::GrowingUint32HeapArray * arr)
- {
- if (arr == nullptr || arr->Count() == 0 || arr->GetLength() == 0 || arr->GetBuffer() == nullptr)
- {
- return PrependInt32(builder, clue, 0);
- }
- auto size = PrependInt32(builder, clue, arr->Count());
- size += PrependUInt32Array(builder, arr->Count(), arr->GetBuffer());
- return size;
- }
- uint32 PrependSmallSpanSequence(BufferBuilderList & builder, LPCWSTR clue, SmallSpanSequence * spanSequence)
- {
- auto size = PrependInt32(builder, clue, spanSequence->baseValue);
- size += PrependGrowingUint32Array(builder, _u("Statement Buffer"), spanSequence->pStatementBuffer);
- size += PrependGrowingUint32Array(builder, _u("Actual Offset List"), spanSequence->pActualOffsetList);
- return size;
- }
- template <typename TStructType>
- uint32 PrependStruct(BufferBuilderList & builder, LPCWSTR clue, TStructType * value)
- {
- auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<TStructType>, clue, *value);
- builder.list = builder.list->Prepend(entry, alloc);
- return sizeof(serialization_alignment TStructType);
- }
- uint32 AddPropertyIdOfFormals(BufferBuilderList & builder, PropertyIdArray * propIds, FunctionBody * function)
- {
- uint32 size = 0;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("Start propertyids of formals"), magicStartOfPropIdsOfFormals);
- #endif
- byte extraSlotCount = 0;
- if (function->HasCachedScopePropIds())
- {
- extraSlotCount = ActivationObjectEx::ExtraSlotCount();
- }
- size += PrependInt32(builder, _u("ExportsIdArrayLength"), propIds->count);
- size += PrependByte(builder, _u("ExtraSlotsCount"), extraSlotCount);
- size += PrependByte(builder, _u("ExportsIdArrayDups"), propIds->hadDuplicates);
- size += PrependByte(builder, _u("ExportsIdArray__proto__"), propIds->has__proto__);
- size += PrependByte(builder, _u("ExportsIdArrayHasNonSimpleParams"), propIds->hasNonSimpleParams);
- for (uint i = 0; i < propIds->count; i++)
- {
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(propIds->elements[i]);
- size += PrependInt32(builder, _u("ExportsIdArrayElem"), propertyId);
- }
- auto slots = propIds->elements + propIds->count;
- for (byte i = 0; i < extraSlotCount; i++)
- {
- size += PrependInt32(builder, _u("Extra Slot"), slots[i]);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End of prop ids for formals array"), magicEndOfPropIdsOfFormals);
- #endif
- return size;
- }
- #ifdef ASMJS_PLAT
- uint32 AddAsmJsFunctionInfo(BufferBuilderList & builder, FunctionBody * function)
- {
- uint32 size = 0;
- AsmJsFunctionInfo* funcInfo = function->GetAsmJsFunctionInfo();
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Start Asm.js Function Info"), magicStartOfAsmJsFuncInfo);
- #endif
- size += PrependInt32(builder, _u("ReturnType"), funcInfo->GetReturnType().which());
- size += PrependInt16(builder, _u("ArgCount"), funcInfo->GetArgCount());
- size += PrependInt16(builder, _u("ArgSize"), funcInfo->GetArgByteSize());
- size += PrependInt16(builder, _u("ArgSizeArrayLength"), funcInfo->GetArgSizeArrayLength());
- size += PrependUInt32Array(builder, funcInfo->GetArgSizeArrayLength(), funcInfo->GetArgsSizesArray());
- size += PrependByteArray(builder, funcInfo->GetArgCount(), (byte*)funcInfo->GetArgTypeArray());
- size += PrependByte(builder, _u("UsesHeapBuffer"), funcInfo->UsesHeapBuffer());
- for (int i = WAsmJs::LIMIT - 1; i >= 0; --i)
- {
- const char16* clue = nullptr;
- switch (i)
- {
- case WAsmJs::INT32: clue = _u("Int32TypedSlots"); break;
- case WAsmJs::INT64: clue = _u("Int64TypedSlots"); break;
- case WAsmJs::FLOAT32: clue = _u("Float32TypedSlots"); break;
- case WAsmJs::FLOAT64: clue = _u("Float64TypedSlots"); break;
- case WAsmJs::SIMD: clue = _u("SimdTypedSlots"); break;
- default:
- CompileAssert(WAsmJs::SIMD == WAsmJs::LastType);
- Assert(false);
- break;
- }
- size += PrependStruct<WAsmJs::TypedSlotInfo>(builder, clue, funcInfo->GetTypedSlotInfo((WAsmJs::Types)i));
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End Asm.js Function Info"), magicEndOfAsmJsFuncInfo);
- #endif
- return size;
- }
- uint32 AddAsmJsModuleInfo(BufferBuilderList & builder, FunctionBody * function)
- {
- uint32 size = 0;
- AsmJsModuleInfo * moduleInfo = function->GetAsmJsModuleInfo();
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Start Asm.js Module Info"), magicStartOfAsmJsModuleInfo);
- #endif
- size += PrependInt32(builder, _u("ArgInCount"), moduleInfo->GetArgInCount());
- size += PrependInt32(builder, _u("ExportsCount"), moduleInfo->GetExportsCount());
- size += PrependInt32(builder, _u("SlotsCount"), moduleInfo->GetSlotsCount());
- if (moduleInfo->GetExportsCount() > 0)
- {
- PropertyIdArray * propArray = moduleInfo->GetExportsIdArray();
- size += PrependByte(builder, _u("ExtraSlotsCount"), propArray->extraSlots);
- size += PrependByte(builder, _u("ExportsIdArrayDups"), propArray->hadDuplicates);
- size += PrependByte(builder, _u("ExportsIdArray__proto__"), propArray->has__proto__);
- size += PrependInt32(builder, _u("ExportsIdArrayLength"), propArray->count);
- for (uint i = 0; i < propArray->count; i++)
- {
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(propArray->elements[i]);
- size += PrependInt32(builder, _u("ExportsIdArrayElem"), propertyId);
- }
- size += PrependUInt32Array(builder, moduleInfo->GetExportsCount(), moduleInfo->GetExportsFunctionLocation());
- }
- size += PrependInt32(builder, _u("ExportFunctionIndex"), moduleInfo->GetExportFunctionIndex());
- size += PrependInt32(builder, _u("VarCount"), moduleInfo->GetVarCount());
- for (int i = 0; i < moduleInfo->GetVarCount(); i++)
- {
- size += PrependStruct(builder, _u("ModuleVar"), &moduleInfo->GetVar(i));
- }
- size += PrependInt32(builder, _u("VarImportCount"), moduleInfo->GetVarImportCount());
- for (int i = 0; i < moduleInfo->GetVarImportCount(); i++)
- {
- auto import = moduleInfo->GetVarImport(i);
- size += PrependInt32(builder, _u("ImportLocation"), import.location);
- size += PrependByte(builder, _u("ImportType"), import.type);
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(import.field);
- size += PrependInt32(builder, _u("ImportId"), propertyId);
- }
- size += PrependInt32(builder, _u("FunctionImportCount"), moduleInfo->GetFunctionImportCount());
- for (int i = 0; i < moduleInfo->GetFunctionImportCount(); i++)
- {
- auto import = moduleInfo->GetFunctionImport(i);
- size += PrependInt32(builder, _u("ImportLocation"), import.location);
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(import.field);
- size += PrependInt32(builder, _u("ImportId"), propertyId);
- }
- size += PrependInt32(builder, _u("FunctionCount"), moduleInfo->GetFunctionCount());
- for (int i = 0; i < moduleInfo->GetFunctionCount(); i++)
- {
- auto func = moduleInfo->GetFunction(i);
- size += PrependInt32(builder, _u("FuncLocation"), func.location);
- }
- size += PrependInt32(builder, _u("FunctionTableCount"), moduleInfo->GetFunctionTableCount());
- for (int i = 0; i < moduleInfo->GetFunctionTableCount(); i++)
- {
- auto table = moduleInfo->GetFunctionTable(i);
- size += PrependInt32(builder, _u("FuncTableSize"), table.size);
- PrependUInt32Array(builder, table.size, table.moduleFunctionIndex);
- }
- size += PrependStruct<AsmJsModuleMemory>(builder, _u("ModuleMemory"), &moduleInfo->GetModuleMemory());
- size += PrependInt32(builder, _u("AsmJsSlotMapCount"), moduleInfo->GetAsmJsSlotMap()->Count());
- auto slotIter = moduleInfo->GetAsmJsSlotMap()->GetIterator();
- while (slotIter.IsValid())
- {
- PropertyId propertyId = encodePossiblyBuiltInPropertyId(slotIter.CurrentKey());
- size += PrependInt32(builder, _u("AsmJsSlotPropId"), propertyId);
- size += PrependStruct(builder, _u("AsmJsSlotValue"), slotIter.CurrentValue());
- slotIter.MoveNext();
- }
- size += PrependStruct(builder, _u("MathBuiltinBV"), &moduleInfo->GetAsmMathBuiltinUsed());
- size += PrependStruct(builder, _u("ArrayBuiltinBV"), &moduleInfo->GetAsmArrayBuiltinUsed());
- size += PrependInt32(builder, _u("MaxHeapAccess"), moduleInfo->GetMaxHeapAccess());
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- size += PrependInt32(builder, _u("End Asm.js Module Info"), magicEndOfAsmJsModuleInfo);
- #endif
- return size;
- }
- #endif
- HRESULT AddFunctionBody(BufferBuilderList &builder, FunctionBody *function, SRCINFO const *srcInfo, SerializedFieldList& definedFields)
- {
- Assert(!function->GetIsSerialized());
- DebugOnly(function->SetIsSerialized(true));
- // This field should always be non-zero
- Assert(function->GetConstantCount() != 0);
- #define PrependArgSlot PrependInt16
- #define PrependRegSlot PrependInt32
- #define PrependCharCount PrependInt32
- #define PrependULong PrependInt32
- #define PrependUInt16 PrependInt16
- #define PrependUInt32 PrependInt32
- {
- #define DEFINE_FUNCTION_BODY_FIELDS 1
- #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
- if (function->##name != 0) { \
- definedFields.has_##name = true; \
- Prepend##serializableType(builder, _u(#name), function->##name); \
- }
- #define DECLARE_SERIALIZABLE_ACCESSOR_FIELD_NO_CHECK(type, name, serializableType) \
- Prepend##serializableType(builder, _u(#name), function->Get##name##());
- #define DECLARE_SERIALIZABLE_ACCESSOR_FIELD(type, name, serializableType, defaultValue) \
- if (function->Get##name##() != defaultValue) { \
- definedFields.has_##name = true; \
- DECLARE_SERIALIZABLE_ACCESSOR_FIELD_NO_CHECK(type, name, serializableType); \
- }
- #include "SerializableFunctionFields.h"
- }
- {
- auto loopHeaderArray = function->GetLoopHeaderArray();
- if (loopHeaderArray != nullptr)
- {
- definedFields.has_loopHeaderArray = true;
- uint loopCount = function->GetLoopCount();
- for (uint i = 0; i < loopCount; ++i)
- {
- PrependInt32(builder, _u("Loop Header Start"), loopHeaderArray[i].startOffset);
- PrependInt32(builder, _u("Loop Header End"), loopHeaderArray[i].endOffset);
- }
- }
- #ifdef ASMJS_PLAT
- if (function->GetAsmJsFunctionInfo())
- {
- definedFields.has_asmJsInfo = true;
- PrependByte(builder, _u("Asm.js Info Kind"), 1);
- AddAsmJsFunctionInfo(builder, function);
- }
- else if (function->GetIsAsmjsMode())
- {
- definedFields.has_asmJsInfo = true;
- PrependByte(builder, _u("Asm.js Info Kind"), 2);
- AddAsmJsModuleInfo(builder, function);
- }
- #endif
- #ifdef ASMJS_PLAT
- if (function->GetIsAsmJsFunction())
- {
- AddAsmJsConstantTable(builder, function);
- auto hr = RewriteAsmJsByteCodesInto(builder, _u("Rewritten Asm.js Byte Code"), function, function->byteCodeBlock, definedFields);
- if (FAILED(hr))
- {
- return hr;
- }
- }
- else
- #endif
- {
- AddConstantTable(builder, function);
- auto hr = RewriteByteCodesInto(builder, _u("Rewritten Byte Code"), function, function->byteCodeBlock, definedFields);
- if (FAILED(hr))
- {
- return hr;
- }
- }
- PropertyIdArray * propIds = function->GetFormalsPropIdArray(false);
- if (propIds != nullptr)
- {
- definedFields.has_propertyIdOfFormals = true;
- AddPropertyIdOfFormals(builder, propIds, function);
- }
- AddCacheIdToPropertyIdMap(builder, function);
- AddReferencedPropertyIdMap(builder, function);
- AddPropertyIdsForScopeSlotArray(builder, function);
- if (function->GetSlotIdInCachedScopeToNestedIndexArray() == nullptr)
- {
- definedFields.has_slotIdInCachedScopeToNestedIndexArray = false;
- }
- else
- {
- definedFields.has_slotIdInCachedScopeToNestedIndexArray = true;
- AddSlotIdInCachedScopeToNestedIndexArray(builder, function);
- }
- uint debuggerScopeSlotArraySize = GetDebuggerScopeSlotArrayCount(function);
- if (debuggerScopeSlotArraySize != 0)
- {
- definedFields.has_debuggerScopeSlotArray = true;
- PrependInt32(builder, _u("Debugger Scope Slot Array Size"), debuggerScopeSlotArraySize);
- AddSlotArrayDebuggerScopes(builder, function, debuggerScopeSlotArraySize);
- }
- // Literal regexes
- for (uint i = 0; i < function->GetLiteralRegexCount(); ++i)
- {
- const auto literalRegex = function->GetLiteralRegex(i);
- if (!literalRegex)
- {
- PrependInt32(builder, _u("Literal regex source length"), -1);
- continue;
- }
- const auto source = literalRegex->GetSource();
- PrependInt32(builder, _u("Literal regex source length"), source.GetLength());
- PrependString16(builder, _u("Literal regex source"), source.GetBuffer(), (source.GetLength() + 1) * sizeof(char16));
- PrependByte(builder, _u("Literal regex flags"), literalRegex->GetFlags());
- }
- // Write the SourceInfo stuff
- PrependSmallSpanSequence(builder, _u("Span Sequence"), function->m_sourceInfo.pSpanSequence);
- }
- return S_OK;
- }
- HRESULT AddFunction(BufferBuilderList & builder, ParseableFunctionInfo * function, SRCINFO const * srcInfo)
- {
- SerializedFieldList definedFields = { 0 };
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("Start Function Table"), magicStartOfFunctionBody);
- #endif
- uint32 sourceDiff = 0;
- if (!TryConvertToUInt32(function->StartOffset(), &sourceDiff))
- {
- Assert(0); // Likely a bug
- return ByteCodeSerializer::CantGenerate;
- }
- if (function->m_lineNumber != 0)
- {
- definedFields.has_m_lineNumber = true;
- PrependInt32(builder, _u("Line Number"), function->m_lineNumber);
- }
- if (function->m_columnNumber != 0)
- {
- definedFields.has_m_columnNumber = true;
- PrependInt32(builder, _u("Column Number"), function->m_columnNumber);
- }
- bool isAnonymous = function->GetIsAnonymousFunction();
- // FunctionBody Details
- DWORD bitFlags =
- (function->m_isDeclaration ? ffIsDeclaration : 0)
- | (function->m_hasImplicitArgIns ? ffHasImplicitArgsIn : 0)
- | (function->m_isAccessor ? ffIsAccessor : 0)
- | (function->m_isStaticNameFunction ? ffIsStaticNameFunction : 0)
- | (function->m_isNamedFunctionExpression ? ffIsNamedFunctionExpression : 0)
- | (function->m_isNameIdentifierRef ? ffIsNameIdentifierRef : 0)
- | (function->m_isGlobalFunc ? ffIsGlobalFunc : 0)
- | (function->m_dontInline ? ffDontInline : 0)
- | (function->m_isStrictMode ? ffIsStrictMode : 0)
- | (function->m_doBackendArgumentsOptimization ? ffDoBackendArgumentsOptimization : 0)
- | (function->m_doScopeObjectCreation ? ffDoScopeObjectCreation : 0)
- | (function->m_usesArgumentsObject ? ffUsesArgumentsObject : 0)
- | (function->m_isEval ? ffIsEval : 0)
- | (function->m_isDynamicFunction ? ffIsDynamicFunction : 0)
- | (isAnonymous ? ffIsAnonymous : 0)
- #ifdef ASMJS_PLAT
- | (function->m_isAsmjsMode ? ffIsAsmJsMode : 0)
- | (function->m_isAsmJsFunction ? ffIsAsmJsFunction : 0)
- #endif
- ;
- FunctionBody *functionBody = nullptr;
- if (function->IsFunctionBody())
- {
- functionBody = function->GetFunctionBody();
- bitFlags |=
- (functionBody->m_isFuncRegistered ? ffIsFuncRegistered : 0)
- | (functionBody->m_hasAllNonLocalReferenced ? ffhasAllNonLocalReferenced : 0)
- | (functionBody->m_hasSetIsObject ? ffhasSetIsObject : 0)
- | (functionBody->m_CallsEval ? ffhasSetCallsEval : 0)
- | (functionBody->m_ChildCallsEval ? ffChildCallsEval : 0)
- | (functionBody->m_hasReferenceableBuiltInArguments ? ffHasReferenceableBuiltInArguments : 0)
- | (functionBody->m_isParamAndBodyScopeMerged ? ffIsParamAndBodyScopeMerged : 0);
- }
- PrependConstantInt32(builder, _u("BitFlags"), bitFlags);
- if (!isAnonymous)
- {
- const char16* displayName = function->GetDisplayName();
- uint displayNameLength = function->m_displayNameLength;
- PrependString16(builder, _u("Display Name"), displayName, (displayNameLength + 1) * sizeof(char16));
- }
- PrependInt32(builder, _u("Relative Function ID"), function->GetLocalFunctionId() - topFunctionId); // Serialized function ids are relative to the top function ID
- auto attributes = function->GetAttributes();
- AssertMsg((attributes &
- ~(FunctionInfo::Attributes::ErrorOnNew
- | FunctionInfo::Attributes::SuperReference
- | FunctionInfo::Attributes::Lambda
- | FunctionInfo::Attributes::Async
- | FunctionInfo::Attributes::CapturesThis
- | FunctionInfo::Attributes::Generator
- | FunctionInfo::Attributes::ClassConstructor
- | FunctionInfo::Attributes::BaseConstructorKind
- | FunctionInfo::Attributes::ClassMethod
- | FunctionInfo::Attributes::Method
- | FunctionInfo::Attributes::EnclosedByGlobalFunc
- | FunctionInfo::Attributes::AllowDirectSuper
- | FunctionInfo::Attributes::DeferredParse
- | FunctionInfo::Attributes::CanDefer
- | FunctionInfo::Attributes::ComputedName)) == 0,
- "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");
- if (attributes != FunctionInfo::Attributes::None)
- {
- definedFields.has_attributes = true;
- PrependInt32(builder, _u("Attributes"), attributes);
- }
-
- PrependInt32(builder, _u("Offset Into Source"), sourceDiff);
- if (function->GetNestedCount() > 0)
- {
- definedFields.has_m_nestedCount = true;
- PrependInt32(builder, _u("Nested count"), function->GetNestedCount());
- }
- DeferredFunctionStub* deferredStubs = function->GetDeferredStubs();
- if (deferredStubs != nullptr
- && (attributes & FunctionInfo::Attributes::DeferredParse) != 0
- && GenerateParserStateCache())
- {
- definedFields.has_deferredStubs = true;
- AddDeferredStubs(builder, deferredStubs, function->GetNestedCount(), true);
- }
- #define PrependArgSlot PrependInt16
- #define PrependRegSlot PrependInt32
- #define PrependCharCount PrependInt32
- #define PrependULong PrependInt32
- #define PrependUInt16 PrependInt16
- #define PrependUInt32 PrependInt32
- #define DEFINE_FUNCTION_PROXY_FIELDS 1
- #define DEFINE_PARSEABLE_FUNCTION_INFO_FIELDS 1
- #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
- if (function->##name != 0) { \
- definedFields.has_##name = true; \
- Prepend##serializableType(builder, _u(#name), function->##name); \
- }
- #include "SerializableFunctionFields.h"
- if (functionBody != nullptr)
- {
- AddFunctionBody(builder, functionBody, srcInfo, definedFields);
- }
- // Lastly, write each of the lexically enclosed functions
- if (function->GetNestedCount())
- {
- auto nestedBodyList = Anew(alloc, BufferBuilderList, _u("Nest Function Bodies"));
- for (uint32 i = 0; i < function->GetNestedCount(); ++i)
- {
- auto nestedFunction = function->GetNestedFunc(i);
- if (nestedFunction == nullptr || !nestedFunction->HasParseableInfo())
- {
- PrependConstantInt32(builder, _u("Empty Nested Function"), 0);
- ++functionCount.value;
- }
- else
- {
- auto nestedFunctionBuilder = Anew(alloc, BufferBuilderList, _u("Nested Function"));
- nestedBodyList->list = nestedBodyList->list->Prepend(nestedFunctionBuilder, alloc);
- auto offsetToNested = Anew(alloc, BufferBuilderRelativeOffset, _u("Offset To Nested Function"), nestedFunctionBuilder);
- builder.list = builder.list->Prepend(offsetToNested, alloc);
- AddFunction(*nestedFunctionBuilder, nestedFunction->GetParseableFunctionInfo(), srcInfo);
- }
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("End Function Body"), magicEndOfFunctionBody);
- #endif
- builder.list = builder.list->Prepend(nestedBodyList, alloc);
- }
- else
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- PrependInt32(builder, _u("End Function Body"), magicEndOfFunctionBody);
- #endif
- }
- // Increment the function count
- ++functionCount.value;
- // Reverse to put prepended items in correct order
- builder.list = builder.list->ReverseCurrentList();
- PrependStruct<SerializedFieldList>(builder, _u("Serialized Field List"), &definedFields);
- return S_OK;
- }
- HRESULT AddTopFunctionBody(FunctionBody * function, SRCINFO const * srcInfo)
- {
- topFunctionId = function->GetLocalFunctionId();
- return AddFunction(functionsTable, function, srcInfo);
- }
- HRESULT AddDeferredStubs(BufferBuilderList & builder, DeferredFunctionStub* deferredStubs, uint stubsCount, bool recursive)
- {
- if (deferredStubs == nullptr || stubsCount == 0)
- {
- return S_OK;
- }
- for (uint i = 0; i < stubsCount; i++)
- {
- DeferredFunctionStub* currentStub = &(deferredStubs[i]);
- PrependUInt32(builder, _u("Character Min"), currentStub->ichMin);
- PrependUInt32(builder, _u("Function flags"), currentStub->fncFlags);
- PrependStruct(builder, _u("Restore Point"), &(currentStub->restorePoint));
- // Add all the captured name ids
- IdentPtrSet *capturedNames = currentStub->capturedNamePointers;
- if (capturedNames != nullptr && capturedNames->Count() != 0)
- {
- uint capturedNamesCount = capturedNames->Count();
- auto iter = capturedNames->GetIterator();
- PrependUInt32(builder, _u("Captured Name Count"), capturedNamesCount);
- while (iter.IsValid())
- {
- // The captured names are IdentPtr allocated in Parser arena memory.
- // We have to convert them to indices into our string table to effectively
- // serialize the names.
- const IdentPtr& pid = iter.CurrentValueReference();
- int capturedNameSerializedId = this->GetIdOfString(pid->Psz(), pid->Cch());
- PrependInt32(builder, _u("Captured Name"), capturedNameSerializedId);
- iter.MoveNext();
- }
- }
- else
- {
- PrependUInt32(builder, _u("Captured Name Count"), 0);
- }
- PrependUInt32(builder, _u("Nested Count"), currentStub->nestedCount);
- if (recursive)
- {
- AddDeferredStubs(builder, currentStub->deferredStubs, currentStub->nestedCount, recursive);
- }
- }
- return S_OK;
- }
- };
- class ByteCodeBufferReader
- {
- public:
- ScriptContext * scriptContext;
- byte * raw;
- int magic;
- int totalSize;
- byte fileVersionScheme;
- int V1;
- int V2;
- int V3;
- int V4;
- byte architecture;
- int expectedFunctionBodySize;
- int expectedBuildInPropertyCount;
- int expectedOpCodeCount;
- int firstFunctionId;
- int functionCount;
- const byte * string16s;
- int string16Count;
- const unaligned StringIndexRecord * string16IndexTable;
- const byte * string16Table;
- int lineInfoCacheCount;
- const byte * lineInfoCaches;
- const charcount_t * lineCharacterOffsetCacheBuffer;
- const charcount_t * lineByteOffsetCacheBuffer;
- const byte * functions;
- int sourceSize;
- int sourceCharLength;
- Utf8SourceInfo *utf8SourceInfo;
- uint sourceIndex;
- bool const isLibraryCode;
- public:
- ByteCodeBufferReader(ScriptContext * scriptContext, byte * raw, bool isLibraryCode, int builtInPropertyCount)
- : scriptContext(scriptContext),
- raw(raw),
- magic(0),
- totalSize(0),
- fileVersionScheme(0),
- V1(0),
- V2(0),
- V3(0),
- V4(0),
- architecture(0),
- expectedFunctionBodySize(sizeof(unaligned FunctionBody)),
- expectedBuildInPropertyCount(builtInPropertyCount),
- expectedOpCodeCount((int)OpCode::Count),
- firstFunctionId(0),
- functionCount(0),
- string16s(nullptr),
- string16Count(0),
- string16IndexTable(nullptr),
- string16Table(nullptr),
- lineInfoCacheCount(0),
- lineInfoCaches(nullptr),
- lineCharacterOffsetCacheBuffer(nullptr),
- lineByteOffsetCacheBuffer(nullptr),
- functions(nullptr),
- sourceSize(0),
- sourceCharLength(0),
- utf8SourceInfo(nullptr),
- sourceIndex(0),
- isLibraryCode(isLibraryCode)
- {
- if (isLibraryCode)
- {
- expectedFunctionBodySize = 0;
- expectedOpCodeCount = 0;
- }
- }
- static const byte* ReadFunctionBodyFlags(const byte * buffer, size_t remainingBytes, FunctionBody::FunctionBodyFlags * value)
- {
- Assert(remainingBytes >= sizeof(FunctionBody::FunctionBodyFlags));
- *value = *(FunctionBody::FunctionBodyFlags*) buffer;
- return buffer + sizeof(FunctionBody::FunctionBodyFlags);
- }
- const byte* ReadFunctionBodyFlags(const byte * buffer, FunctionBody::FunctionBodyFlags * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadFunctionBodyFlags(buffer, remainingBytes, value);
- }
- const byte* ReadBool(const byte * buffer, _Out_ bool * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- Assert(remainingBytes >= sizeof(bool));
- *value = *buffer ? true : false;
- return buffer + sizeof(bool);
- }
- static const byte * ReadByte(const byte * buffer, size_t remainingBytes, byte * value)
- {
- Assert(remainingBytes>=sizeof(byte));
- *value = *(byte*)buffer;
- return buffer + sizeof(byte);
- }
- const byte * ReadByte(const byte * buffer, byte * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadByte(buffer, remainingBytes, value);
- }
- static const byte * ReadConstantSizedInt16(const byte * buffer, size_t remainingBytes, int16 * value)
- {
- Assert(remainingBytes >= sizeof(int16));
- *value = *(int16 *)buffer;
- return buffer + sizeof(int16);
- }
- const byte * ReadConstantSizedInt16(const byte * buffer, int16 * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadConstantSizedInt16(buffer, remainingBytes, value);
- }
- static const byte * ReadInt16(const byte * buffer, size_t remainingBytes, int16 * value)
- {
- #if VARIABLE_INT_ENCODING
- return ReadVariableInt<int16>(buffer, remainingBytes, value);
- #else
- Assert(remainingBytes>=sizeof(int16));
- *value = *(int16 *) buffer;
- return buffer + sizeof(int16);
- #endif
- }
- const byte * ReadInt16(const byte * buffer, int16 * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt16(buffer, remainingBytes, value);
- }
- static const byte * ReadConstantSizedInt64(const byte * buffer, size_t remainingBytes, int64 * value)
- {
- Assert(remainingBytes >= sizeof(int64));
- *value = *(int64 *)buffer;
- return buffer + sizeof(int64);
- }
- const byte * ReadConstantSizedInt64(const byte * buffer, int64 * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadConstantSizedInt64(buffer, remainingBytes, value);
- }
- static const byte * ReadConstantSizedInt32(const byte * buffer, size_t remainingBytes, int * value)
- {
- Assert(remainingBytes >= sizeof(int));
- *value = *(int *) buffer;
- return buffer + sizeof(int);
- }
- const byte * ReadConstantSizedInt32(const byte * buffer, int * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadConstantSizedInt32(buffer, remainingBytes, value);
- }
- const byte * ReadConstantSizedUInt32(const byte * buffer, uint * value)
- {
- return ReadConstantSizedInt32(buffer, (int *)value);
- }
- static const byte * ReadInt32(const byte * buffer, size_t remainingBytes, int * value)
- {
- #if VARIABLE_INT_ENCODING
- return ReadVariableInt<int>(buffer, remainingBytes, value);
- #else
- Assert(remainingBytes >= sizeof(int));
- return ReadConstantSizedInt32(buffer, remainingBytes, value);
- #endif
- }
- const byte * ReadInt32(const byte * buffer, int * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt32(buffer, remainingBytes, value);
- }
- const byte * ReadCharCount(const byte * buffer, size_t remainingBytes, charcount_t * value)
- {
- #if VARIABLE_INT_ENCODING
- return ReadVariableInt<charcount_t>(buffer, remainingBytes, value);
- #else
- Assert(remainingBytes >= sizeof(charcount_t));
- *value = *(charcount_t *) buffer;
- return buffer + sizeof(charcount_t);
- #endif
- }
- const byte * ReadCharCount(const byte * buffer, charcount_t * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadCharCount(buffer, remainingBytes, value);
- }
- static const byte * ReadFloat(const byte * buffer, size_t remainingBytes, float * value)
- {
- Assert(remainingBytes >= sizeof(float));
- *value = *(float *)buffer;
- return buffer + sizeof(float);
- }
- const byte * ReadFloat(const byte * buffer, float * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadFloat(buffer, remainingBytes, value);
- }
- static const byte * ReadDouble(const byte * buffer, size_t remainingBytes, double * value)
- {
- Assert(remainingBytes>=sizeof(double));
- *value = *(double *)buffer;
- return buffer + sizeof(double);
- }
- const byte * ReadDouble(const byte * buffer, double * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadDouble(buffer, remainingBytes, value);
- }
- static const byte * ReadSIMDValue(const byte * buffer, size_t remainingBytes, SIMDValue * value)
- {
- Assert(remainingBytes >= sizeof(SIMDValue));
- *value = *(SIMDValue *)buffer;
- return buffer + sizeof(SIMDValue);
- }
- const byte * ReadSIMDValue(const byte * buffer, SIMDValue * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadSIMDValue(buffer, remainingBytes, value);
- }
- const byte * ReadUInt16(const byte * buffer, uint16 * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt16(buffer, remainingBytes, (int16*)value);
- }
- const byte * ReadUInt32(const byte * buffer, unsigned int * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt32(buffer, remainingBytes, (int*)value);
- }
- const byte * ReadULong(const byte * buffer, uint32 * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt32(buffer, remainingBytes, (int*)value);
- }
- const byte * ReadRegSlot(const byte * buffer, RegSlot * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt32(buffer, remainingBytes, (int*)value);
- }
- const byte * ReadArgSlot(const byte * buffer, ArgSlot * value)
- {
- auto remainingBytes = (raw + totalSize) - buffer;
- return ReadInt32(buffer, remainingBytes, (int*)value);
- }
- const byte * ReadConstantSizedInt32NoSize(const byte * buffer, int * value)
- {
- *value = *(int *)buffer;
- return buffer + sizeof(int);
- }
- template <typename TStructType>
- const byte * ReadStruct(const byte * buffer, serialization_alignment TStructType ** value)
- {
- *value = (serialization_alignment TStructType*)buffer;
- return buffer + sizeof(serialization_alignment TStructType);
- }
- const byte * ReadOffsetAsPointer(const byte * buffer, byte const ** value)
- {
- int offset;
- auto next = ReadConstantSizedInt32(buffer, &offset);
- if (offset == 0)
- {
- *value = nullptr;
- return next;
- }
- *value = raw + offset;
- return next;
- }
- template<typename Fn>
- const byte * ReadByteBlock(const byte * buffer, Fn fn)
- {
- int contentLength;
- buffer = ReadInt32(buffer, &contentLength);
- fn(contentLength, buffer);
- return buffer + contentLength;
- }
- const byte * ReadAuxiliary(const byte * buffer, FunctionBody * functionBody)
- {
- const byte * current = buffer;
- uint32 countOfAuxiliaryStructure;
- current = ReadUInt32(current, &countOfAuxiliaryStructure);
- Assert(countOfAuxiliaryStructure != 0);
-
- uint32 sizeOfAuxiliaryBlock;
- uint32 sizeOfAuxiliaryContextBlock;
- current = ReadUInt32(current, &sizeOfAuxiliaryBlock);
- current = ReadUInt32(current, &sizeOfAuxiliaryContextBlock);
- ByteBlock * auxBlock = sizeOfAuxiliaryBlock?
- ByteBlock::New(scriptContext->GetRecycler(), nullptr, sizeOfAuxiliaryBlock) : nullptr;
- ByteBlock * auxContextBlock = sizeOfAuxiliaryContextBlock?
- ByteBlock::New(scriptContext->GetRecycler(), nullptr, sizeOfAuxiliaryContextBlock) : nullptr;
- for (uint i = 0; i < countOfAuxiliaryStructure; i++)
- {
- typedef serialization_alignment const SerializedAuxiliary TBase;
- auto part = (serialization_alignment const SerializedAuxiliary * )current;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- Assert(part->auxMagic == magicStartOfAux);
- #endif
- switch(part->kind)
- {
- default:
- AssertMsg(false, "Unexpected auxiliary kind");
- Throw::FatalInternalError();
- break;
- case sakVarArrayIntCount:
- current = DeserializeVarArray<VarArray>(scriptContext, current, auxBlock);
- break;
- case sakVarArrayVarCount:
- current = DeserializeVarArray<VarArrayVarCount>(scriptContext, current, auxContextBlock);
- break;
- case sakIntArray:
- current = DeserializeIntArray(scriptContext, current, auxBlock);
- break;
- case sakFloatArray:
- current = DeserializeFloatArray(scriptContext, current, auxBlock);
- break;
- case sakPropertyIdArray:
- current = DeserializePropertyIdArray(scriptContext, current, auxBlock, functionBody);
- break;
- case sakFuncInfoArray:
- current = DeserializeFuncInfoArray(scriptContext, current, auxBlock);
- break;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int magicEnd;
- current = ReadInt32(current, &magicEnd);
- Assert(magicEnd == magicEndOfAux);
- #endif
- }
- functionBody->SetAuxiliaryData(auxBlock);
- functionBody->SetAuxiliaryContextData(auxContextBlock);
- return current;
- }
- LPCWSTR GetString16ById(int id, bool* isPropertyRecord = nullptr)
- {
- if (id == 0xffffffff)
- {
- return nullptr;
- }
- if(!(id >= this->expectedBuildInPropertyCount && id <= string16Count + this->expectedBuildInPropertyCount))
- {
- Assert(false);
- }
- const unaligned StringIndexRecord* record = string16IndexTable + (id - this->expectedBuildInPropertyCount);
- if(isPropertyRecord)
- {
- *isPropertyRecord = record->isPropertyRecord;
- }
- auto offset = record->offset;
- auto addressOfString = raw + offset;
- return (LPCWSTR)addressOfString;
- }
- uint32 GetString16LengthById(int id)
- {
- if(!(id >= this->expectedBuildInPropertyCount && id<=string16Count + this->expectedBuildInPropertyCount))
- {
- Assert(false);
- }
- LPCWSTR s1 = GetString16ById(id);
- LPCWSTR s2 = GetString16ById(id + 1);
- auto result = s2 - s1 - 1;
- Assert(result <= UINT_MAX);
- return (uint32)result;
- }
- HRESULT ReadHeader()
- {
- auto current = ReadConstantSizedInt32NoSize(raw, &magic);
- if (magic != magicConstant)
- {
- AssertMsg(false, "Unrecognized magic constant in byte code file header. Is this really a bytecode file?");
- return E_FAIL;
- }
- current = ReadConstantSizedInt32NoSize(current, &totalSize);
- current = ReadByte(current, &fileVersionScheme);
- byte expectedFileVersionScheme = isLibraryCode? LibraryByteCodeVersioningScheme : CurrentFileVersionScheme;
- #if ENABLE_DEBUG_CONFIG_OPTIONS
- if (Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema)
- {
- expectedFileVersionScheme = (byte)Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema;
- }
- #endif
- // Ignore the version scheme check if it is library code
- if (!isLibraryCode && fileVersionScheme != expectedFileVersionScheme)
- {
- // File version scheme is incompatible.
- return ByteCodeSerializer::InvalidByteCode;
- }
- DWORD expectedV1 = 0;
- DWORD expectedV2 = 0;
- DWORD expectedV3 = 0;
- DWORD expectedV4 = 0;
- switch (expectedFileVersionScheme)
- {
- case EngineeringVersioningScheme:
- {
- Js::VerifyCatastrophic(!isLibraryCode);
- Js::VerifyOkCatastrophic(AutoSystemInfo::GetJscriptFileVersion(&expectedV1, &expectedV2, &expectedV3, &expectedV4));
- break;
- }
- case ReleaseVersioningScheme:
- {
- Js::VerifyCatastrophic(!isLibraryCode);
- auto guidDWORDs = (DWORD*)(&byteCodeCacheReleaseFileVersion);
- expectedV1 = guidDWORDs[0];
- expectedV2 = guidDWORDs[1];
- expectedV3 = guidDWORDs[2];
- expectedV4 = guidDWORDs[3];
- break;
- }
- case LibraryByteCodeVersioningScheme:
- {
- // To keep consistent library code between Chakra.dll and ChakraCore.dll, use a fixed version.
- // This goes hand in hand with the bytecode verification unit tests.
- Js::VerifyCatastrophic(isLibraryCode);
- expectedV1 = 0;
- expectedV2 = 0;
- expectedV3 = 0;
- expectedV4 = 0;
- break;
- }
- default:
- Throw::InternalError();
- break;
- }
- #if ENABLE_DEBUG_CONFIG_OPTIONS
- if (Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion)
- {
- expectedV1 = Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion;
- expectedV2 = 0;
- expectedV3 = 0;
- expectedV4 = 0;
- }
- #endif
- current = ReadConstantSizedInt32(current, &V1);
- if ((DWORD)V1!=expectedV1)
- {
- // Incompatible major version
- return ByteCodeSerializer::InvalidByteCode;
- }
- // Library code is serialized with one build of the engine and then included into a subsequent build, so can't have match
- // on the build timestamp hash. Also want to share the generated bytecode between x86/ARM and debug/release, so skip the extra
- // checking. Will rework this validation entirely under TFS 555060
- current = ReadConstantSizedInt32(current, &V2);
- if ((DWORD)V2 != expectedV2)
- {
- // Incompatible minor version
- return ByteCodeSerializer::InvalidByteCode;
- }
- current = ReadConstantSizedInt32(current, &V3);
- if ((DWORD)V3 != expectedV3)
- {
- // Incompatible 3rd version part
- return ByteCodeSerializer::InvalidByteCode;
- }
- current = ReadConstantSizedInt32(current, &V4);
- if ((DWORD)V4 != expectedV4)
- {
- // Incompatible 4th version part
- return ByteCodeSerializer::InvalidByteCode;
- }
- current = ReadByte(current, &architecture);
- if (architecture!=magicArchitecture)
- {
- // This byte cache file was created with against a chakra running under a different architecture. It is incompatible.
- return ByteCodeSerializer::InvalidByteCode;
- }
- int functionBodySize, buildInPropertyCount, opCodeCount;
- current = ReadInt32(current, &functionBodySize);
- if (functionBodySize != expectedFunctionBodySize)
- {
- // The size of function body didn't match. It is incompatible.
- return ByteCodeSerializer::InvalidByteCode;
- }
- current = ReadInt32(current, &buildInPropertyCount);
- if (buildInPropertyCount!=expectedBuildInPropertyCount)
- {
- // This byte cache file was created with against a chakra that has a different number of built in properties. It is incompatible.
- return ByteCodeSerializer::InvalidByteCode;
- }
- current = ReadInt32(current, &opCodeCount);
- if (opCodeCount != expectedOpCodeCount)
- {
- // This byte cache file was created with against a chakra that has a different number of built in properties. It is incompatible.
- return ByteCodeSerializer::InvalidByteCode;
- }
- current = ReadInt32(current, &sourceSize);
- current = ReadInt32(current, &sourceCharLength);
- current = ReadOffsetAsPointer(current, &string16s);
- current = ReadOffsetAsPointer(current, &lineInfoCaches);
- current = ReadOffsetAsPointer(current, &functions);
- // Read strings header
- string16IndexTable = (StringIndexRecord*)ReadInt32(string16s, &string16Count);
- lineCharacterOffsetCacheBuffer = (charcount_t *)ReadInt32(lineInfoCaches, &lineInfoCacheCount);
- byte haslineByteOffsetCacheBuffer;
- current = ReadByte(lineInfoCaches + sizeof(charcount_t) * lineInfoCacheCount, &haslineByteOffsetCacheBuffer);
- if (haslineByteOffsetCacheBuffer)
- {
- lineByteOffsetCacheBuffer = (charcount_t *)current;
- }
- else
- {
- lineByteOffsetCacheBuffer = nullptr;
- }
- string16Table = (byte*)(string16IndexTable + string16Count + 1);
- // string16Table is aligned to 2-bytes
- uint32 string16TableOffset = (uint32)(string16Table - raw);
- string16TableOffset = ::Math::Align(string16TableOffset, (uint32)sizeof(char16));
- string16Table = raw + string16TableOffset;
- return S_OK;
- }
- const byte* ReadStringConstant(const byte* current, FunctionBody* function, _Out_ LPCWSTR * string, _Out_ uint32 * len)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartStringConstant);
- #endif
- int stringId;
- current = ReadInt32(current, &stringId);
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndStringConstant);
- #endif
- *string = GetString16ById(stringId);
- *len = GetString16LengthById(stringId);
- return current;
- }
- const byte* ReadStringTemplateCallsiteConstant(const byte* current, FunctionBody* function, Var& var)
- {
- int arrayLength = 0;
- current = ReadInt32(current, &arrayLength);
- ScriptContext* scriptContext = function->GetScriptContext();
- ENTER_PINNED_SCOPE(Js::JavascriptArray, callsite);
- callsite = scriptContext->GetLibrary()->CreateArray(arrayLength);
- LPCWSTR string;
- uint32 len;
- uint32 rawlen = 0;
- for (int i = 0; i < arrayLength; i++)
- {
- current = ReadStringConstant(current, function, &string, &len);
- JavascriptString* str = JavascriptString::NewCopyBuffer(string, len, scriptContext);
- callsite->SetItemWithAttributes(i, str, PropertyEnumerable);
- }
- JavascriptArray* rawArray = scriptContext->GetLibrary()->CreateArray(arrayLength);
- for (int i = 0; i < arrayLength; i++)
- {
- current = ReadStringConstant(current, function, &string, &len);
- rawlen += len;
- JavascriptString* str = JavascriptString::NewCopyBuffer(string, len, scriptContext);
- rawArray->SetItemWithAttributes(i, str, PropertyEnumerable);
- }
- rawArray->Freeze();
- callsite->SetPropertyWithAttributes(Js::PropertyIds::raw, rawArray, PropertyNone, nullptr);
- callsite->Freeze();
- JavascriptLibrary* library = scriptContext->GetLibrary();
- var = library->TryGetStringTemplateCallsiteObject(callsite);
- if (var == nullptr)
- {
- library->AddStringTemplateCallsiteObject(callsite);
- var = callsite;
- }
- LEAVE_PINNED_SCOPE();
- return current;
- }
- #ifdef ASMJS_PLAT
- const byte * ReadAsmJsConstantsTable(const byte * current, FunctionBody * function)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfConstantTable);
- #endif
- function->CreateConstantTable();
- auto constTable = function->GetConstTable();
- byte* tableEnd = (byte*)(constTable + function->GetConstantCount());
- for (int i = 0; i < WAsmJs::LIMIT; ++i)
- {
- WAsmJs::Types type = (WAsmJs::Types)i;
- WAsmJs::TypedSlotInfo* typedInfo = function->GetAsmJsFunctionInfo()->GetTypedSlotInfo(type);
- uint32 constCount = typedInfo->constCount;
- if (constCount > FunctionBody::FirstRegSlot)
- {
- uint32 typeSize = WAsmJs::GetTypeByteSize(type);
- byte* byteTable = ((byte*)constTable) + typedInfo->constSrcByteOffset;
- byteTable += typeSize * FunctionBody::FirstRegSlot;
- size_t remainingBytes = (raw + totalSize) - current;
- for (uint32 reg = FunctionBody::FirstRegSlot; reg < constCount; ++reg)
- {
- switch (type)
- {
- case WAsmJs::INT32: ReadConstantSizedInt32(current, remainingBytes, (int*)byteTable); break;
- case WAsmJs::FLOAT32: ReadFloat(current, remainingBytes, (float*)byteTable); break;
- case WAsmJs::FLOAT64: ReadDouble(current, remainingBytes, (double*)byteTable); break;
- default:
- Assert(UNREACHED);
- Js::Throw::FatalInternalError();
- break;
- }
- current += typeSize;
- byteTable += typeSize;
- remainingBytes -= typeSize;
- }
- if (byteTable > tableEnd)
- {
- Assert(UNREACHED);
- Js::Throw::FatalInternalError();
- }
- }
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfConstantTable);
- #endif
- return current;
- }
- #endif
- const byte * ReadConstantsTable(const byte * current, FunctionBody * function)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfConstantTable);
- #endif
- function->CreateConstantTable();
- for (auto reg = FunctionBody::FirstRegSlot + 1; reg < function->GetConstantCount(); reg++) // Ignore first slot, it is always global or module root and has been preinitialized.
- {
- byte ct;
- current = ReadByte(current, &ct);
- switch(ct)
- {
- case ctString16:
- {
- LPCWSTR string;
- uint32 len;
- current = ReadStringConstant(current, function, &string, &len);
- function->RecordStrConstant(reg, string, len, false);
- break;
- }
- case ctPropertyString16:
- {
- LPCWSTR string;
- uint32 len;
- current = ReadStringConstant(current, function, &string, &len);
- function->RecordStrConstant(reg, string, len, true);
- break;
- }
- case ctStringTemplateCallsite:
- {
- Var callsite = nullptr;
- current = ReadStringTemplateCallsiteConstant(current, function, callsite);
- function->RecordConstant(reg, callsite);
- break;
- }
- case ctInt32:
- {
- int value;
- current = ReadConstantSizedInt32(current, &value);
- function->RecordIntConstant(reg, value);
- break;
- }
- case ctInt16:
- {
- int16 value;
- current = ReadConstantSizedInt16(current, &value);
- function->RecordIntConstant(reg, value);
- break;
- }
- case ctInt8:
- {
- int8 value;
- current = ReadByte(current, (byte *)&value);
- function->RecordIntConstant(reg, value);
- break;
- }
- case ctNull:
- function->RecordNullObject(reg);
- break;
- case ctUndefined:
- function->RecordUndefinedObject(reg);
- break;
- case ctNumber:
- {
- double value;
- current = ReadDouble(current, &value);
- function->RecordFloatConstant(reg, value);
- break;
- }
- case ctNullDisplay:
- function->RecordNullDisplayConstant(reg);
- break;
- case ctStrictNullDisplay:
- function->RecordStrictNullDisplayConstant(reg);
- break;
- case ctTrue:
- function->RecordTrueObject(reg);
- break;
- case ctFalse:
- function->RecordFalseObject(reg);
- break;
- default:
- AssertMsg(UNREACHED, "Unexpected object type in ReadConstantsTable");
- break;
- }
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfConstantTable);
- #endif
- return current;
- }
- const byte * ReadPropertyIdsForScopeSlotArray(const byte * current, FunctionBody * function)
- {
- if (function->scopeSlotArraySize == 0)
- {
- return current;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfPropertyIdsForScopeSlotArray);
- #endif
- function->SetPropertyIdsForScopeSlotArray(RecyclerNewArrayLeaf(scriptContext->GetRecycler(), Js::PropertyId, function->scopeSlotArraySize), function->scopeSlotArraySize, function->paramScopeSlotArraySize);
- for (uint i = 0; i < function->scopeSlotArraySize; i++)
- {
- int value;
- current = ReadInt32(current, &value);
- PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(value);
- function->GetPropertyIdsForScopeSlotArray()[i] = propertyId;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfPropertyIdsForScopeSlotArray);
- #endif
- return current;
- }
- const byte * ReadSlotIdInCachedScopeToNestedIndexArray(const byte * current, FunctionBody * functionBody)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfSlotIdToNestedIndexArray);
- #endif
- uint32 count;
- current = ReadUInt32(current, &count);
- Js::AuxArray<uint32> * slotIdInCachedScopeToNestedIndexArray = functionBody->AllocateSlotIdInCachedScopeToNestedIndexArray(count);
-
- uint32 value;
- for (uint i = 0; i < count; i++)
- {
- current = ReadUInt32(current, &value);
- slotIdInCachedScopeToNestedIndexArray->elements[i] = value;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfSlotIdToNestedIndexArray);
- #endif
- return current;
- }
- const byte * ReadSlotArrayDebuggerScopeProperties(const byte * current, FunctionBody* function, DebuggerScope* debuggerScope, uint propertyCount)
- {
- Assert(function);
- Assert(debuggerScope);
- if (propertyCount == 0)
- {
- return current;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfDebuggerScopeProperties);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- for (uint i = 0u; i < propertyCount; ++i)
- {
- // Read the slot array index and property ID for each property (for heap enum to use). The remaining properties
- // are needed for the debugger and will be filled in when generating byte code.
- int value;
- current = ReadInt32(current, &value);
- RegSlot slotIndex = value;
- current = ReadInt32(current, &value);
- PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(value);
- debuggerScope->AddProperty(slotIndex, propertyId, DebuggerScopePropertyFlags_None);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfDebuggerScopeProperties);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- return current;
- }
- const byte * ReadSlotArrayDebuggerScopes(const byte * current, FunctionBody * function, uint debuggerScopeCount)
- {
- Assert(function);
- Assert(debuggerScopeCount != 0);
-
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfDebuggerScopes);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- AssertMsg(function->GetScopeObjectChain() == nullptr, "Scope chain should not exist before deserialization.");
- function->SetScopeObjectChain(RecyclerNew(scriptContext->GetRecycler(), ScopeObjectChain, scriptContext->GetRecycler()));
- int currentScopeOffset = 0;
- for (uint i = 0u; i < debuggerScopeCount; i++)
- {
- int scopeIndex;
- current = ReadInt32(current, &scopeIndex);
- DebuggerScope* slotArrayDebuggerScope = nullptr;
- AssertMsg(currentScopeOffset <= scopeIndex, "Scope indices were not inserted into the serialized byte code in ascending order.");
- while (currentScopeOffset <= scopeIndex)
- {
- // Fill the chain with dummy scopes until we reach the slot array scope we're on.
- // These non-slot array scopes are only needed for the debugger and will be filled in
- // properly during byte code generation (when attaching).
- // We also don't need to worry about the parenting/sibling chain, as this will be built when
- // generating bytecode as well.
- slotArrayDebuggerScope = function->AddScopeObject(Js::DiagUnknownScope, 0, Constants::NoRegister);
- ++currentScopeOffset;
- }
- Assert(slotArrayDebuggerScope);
- // Create the slot array properties.
- int propertyCount;
- current = ReadInt32(current, &propertyCount);
- current = ReadSlotArrayDebuggerScopeProperties(current, function, slotArrayDebuggerScope, propertyCount);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfDebuggerScopes);
- #endif // BYTE_CODE_MAGIC_CONSTANTS
- return current;
- }
- const byte * ReadCacheIdToPropertyIdMap(const byte * current, FunctionBody * function)
- {
- uint count = function->GetInlineCacheCount();
- if (count == 0)
- {
- return current;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfCacheIdToPropIdMap);
- #endif
- function->CreateCacheIdToPropertyIdMap();
- for (uint i = 0; i < count; i++)
- {
- int value;
- current = ReadInt32(current, &value);
- PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(value);
- function->SetPropertyIdForCacheId(i, propertyId);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfCacheIdToPropIdMap);
- #endif
- #if DBG
- function->VerifyCacheIdToPropertyIdMap();
- #endif
- return current;
- }
- const byte * ReadReferencedPropertyIdMap(const byte * current, FunctionBody * function)
- {
- uint count = function->GetReferencedPropertyIdCount();
- if (count == 0)
- {
- return current;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfReferencedPropIdMap);
- #endif
- function->CreateReferencedPropertyIdMap();
- for (uint i = 0; i < count; i++)
- {
- int value;
- current = ReadInt32(current, &value);
- PropertyId propertyId = function->GetByteCodeCache()->LookupNonBuiltinPropertyId(value);
- function->SetReferencedPropertyIdWithMapIndex(i, propertyId);
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfReferencedPropIdMap);
- #endif
- #if DBG
- function->VerifyReferencedPropertyIdMap();
- #endif
- return current;
- }
- // Read a growing Uint32 array
- const byte * ReadGrowingUint32Array(const byte * current, JsUtil::GrowingUint32HeapArray ** arr)
- {
- int count = 0;
- current = ReadInt32(current, &count);
- if (count == 0)
- {
- (*arr) = nullptr;
- return current;
- }
- (*arr) = JsUtil::GrowingUint32HeapArray::Create(/*length=*/count);
- js_memcpy_s((*arr)->GetBuffer(), count * sizeof(uint32), current, count*sizeof(uint32));
- (*arr)->SetCount(count);
- current += count * sizeof(uint32);
- return current;
- }
- // Read a small span sequence
- const byte * ReadSmallSpanSequence(const byte * current, SmallSpanSequence ** smallSpanSequence)
- {
- (*smallSpanSequence) = HeapNew(SmallSpanSequence);
- current = ReadInt32(current, &(*smallSpanSequence)->baseValue);
- current = ReadGrowingUint32Array(current, &(*smallSpanSequence)->pStatementBuffer); // CONSIDER: It would be really nice to change GrowingUint32Array to something with a fixed, readonly layout
- current = ReadGrowingUint32Array(current, &(*smallSpanSequence)->pActualOffsetList);
- return current;
- }
- void ReadSourceInfo(const byte * functionBytes, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction)
- {
- int displayNameId;
- unsigned int bitflags;
- this->ReadFunctionBodyHeader(functionBytes, displayNameId, lineNumber, columnNumber, bitflags);
- m_isEval = (bitflags & ffIsEval) ? true : false;
- m_isDynamicFunction = (bitflags & ffIsDynamicFunction) ? true : false;
- }
- const byte * ReadFunctionBodyHeader(const byte * functionBytes, int& displayNameId, int& lineNumber, int& columnNumber, unsigned int& bitflags)
- {
- serialization_alignment SerializedFieldList* definedFields = (serialization_alignment SerializedFieldList*) functionBytes;
- // Basic function body constructor arguments
- const byte * current = functionBytes + sizeof(serialization_alignment SerializedFieldList);
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfFunctionBody);
- #endif
- if (definedFields->has_m_lineNumber)
- {
- current = ReadInt32(current, &lineNumber);
- }
- else
- {
- lineNumber = 0;
- }
- if (definedFields->has_m_columnNumber)
- {
- current = ReadInt32(current, &columnNumber);
- }
- else
- {
- columnNumber = 0;
- }
- current = ReadConstantSizedUInt32(current, &bitflags);
- if (bitflags & ffIsAnonymous)
- {
- displayNameId = -1;
- }
- else
- {
- current = ReadInt32(current, &displayNameId);
- }
- return current;
- }
- const byte * ReadPropertyIdOfFormals(const byte * current, FunctionBody * function)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant = 0;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfPropIdsOfFormals);
- #endif
- uint32 count = 0;
- current = ReadUInt32(current, &count);
- byte extraSlotCount = 0;
- current = ReadByte(current, &extraSlotCount);
- PropertyIdArray * propIds = function->AllocatePropertyIdArrayForFormals((extraSlotCount + count) * sizeof(PropertyId), count, extraSlotCount);
- propIds->count = count;
- bool hadDuplicates = false;
- current = ReadBool(current, &hadDuplicates);
- propIds->hadDuplicates = hadDuplicates;
- bool has__proto__ = false;
- current = ReadBool(current, &has__proto__);
- propIds->has__proto__ = has__proto__;
- bool hasNonSimpleParams = false;
- current = ReadBool(current, &hasNonSimpleParams);
- propIds->hasNonSimpleParams = hasNonSimpleParams;
- int id = 0;
- for (uint i = 0; i < propIds->count; ++i)
- {
- current = ReadInt32(current, &id);
- PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(id);
- propIds->elements[i] = propertyId;
- }
- for (int i = 0; i < extraSlotCount; ++i)
- {
- current = ReadInt32(current, &id);
- propIds->elements[propIds->count + i] = id;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfPropIdsOfFormals);
- #endif
- return current;
- }
- #ifdef ASMJS_PLAT
- const byte * ReadAsmJsFunctionInfo(const byte * current, FunctionBody * function)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfAsmJsFuncInfo);
- #endif
- AsmJsFunctionInfo* funcInfo = function->AllocateAsmJsFunctionInfo();
- int retVal;
- current = ReadInt32(current, &retVal);
- funcInfo->SetReturnType(AsmJsRetType((AsmJsRetType::Which)retVal));
- ArgSlot argCount;
- current = ReadUInt16(current, &argCount);
- funcInfo->SetArgCount(argCount);
- ArgSlot argByteSize;
- current = ReadUInt16(current, &argByteSize);
- funcInfo->SetArgByteSize(argByteSize);
- ArgSlot argSizeArrayLength;
- current = ReadUInt16(current, &argSizeArrayLength);
- funcInfo->SetArgSizeArrayLength(argSizeArrayLength);
- uint* argArray = RecyclerNewArrayLeafZ(scriptContext->GetRecycler(), uint, argSizeArrayLength);
- funcInfo->SetArgsSizesArray(argArray);
- for (int i = 0; i < argSizeArrayLength; i++)
- {
- int32 size;
- current = ReadConstantSizedInt32(current, &size);
- argArray[i] = (uint32)size;
- }
- if (argCount > 0)
- {
- AsmJsVarType::Which * typeArray = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), AsmJsVarType::Which, argCount);
- funcInfo->SetArgTypeArray(typeArray);
- for (uint i = 0; i < argCount; i++)
- {
- current = ReadByte(current, (byte*)&typeArray[i]);
- }
- }
- bool boolVal;
- current = ReadBool(current, &boolVal);
- funcInfo->SetUsesHeapBuffer(boolVal);
- for (int i = WAsmJs::LIMIT - 1; i >= 0; --i)
- {
- serialization_alignment WAsmJs::TypedSlotInfo* info;
- current = ReadStruct<WAsmJs::TypedSlotInfo>(current, &info);
- WAsmJs::TypedSlotInfo* typedInfo = funcInfo->GetTypedSlotInfo((WAsmJs::Types)i);
- *typedInfo = *info;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfAsmJsFuncInfo);
- #endif
- return current;
- }
- const byte * ReadAsmJsModuleInfo(const byte * current, FunctionBody * function)
- {
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int constant;
- current = ReadInt32(current, &constant);
- Assert(constant == magicStartOfAsmJsModuleInfo);
- #endif
- AsmJsModuleInfo* moduleInfo = function->AllocateAsmJsModuleInfo();
- int count;
- current = ReadInt32(current, &count);
- moduleInfo->SetArgInCount(count);
- int exportsCount;
- current = ReadInt32(current, &exportsCount);
- moduleInfo->SetExportsCount(exportsCount);
- current = ReadInt32(current, &count);
- moduleInfo->InitializeSlotMap(count);
- int id;
- if (exportsCount > 0)
- {
- PropertyIdArray * propArray = moduleInfo->GetExportsIdArray();
- byte extraSlots;
- current = ReadByte(current, &extraSlots);
- propArray->extraSlots = extraSlots;
- bool boolVal;
- current = ReadBool(current, &boolVal);
- propArray->hadDuplicates = boolVal;
- current = ReadBool(current, &boolVal);
- propArray->has__proto__ = boolVal;
- current = ReadInt32(current, &count);
- propArray->count = count;
- for (uint i = 0; i < propArray->count; i++)
- {
- current = ReadInt32(current, &id);
- PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(id);
- propArray->elements[i] = propertyId;
- }
- RegSlot* exportLocations = moduleInfo->GetExportsFunctionLocation();
- for (int i = 0; i < exportsCount; i++)
- {
- int32 loc;
- current = ReadConstantSizedInt32(current, &loc);
- exportLocations[i] = (uint32)loc;
- }
- }
- RegSlot regSlot;
- current = ReadUInt32(current, ®Slot);
- moduleInfo->SetExportFunctionIndex(regSlot);
- current = ReadInt32(current, &count);
- moduleInfo->SetVarCount(count);
- for (int i = 0; i < count; i++)
- {
- serialization_alignment AsmJsModuleInfo::ModuleVar * modVar;
- current = ReadStruct<AsmJsModuleInfo::ModuleVar>(current, &modVar);
- moduleInfo->SetVar(i, *modVar);
- }
- current = ReadInt32(current, &count);
- moduleInfo->SetVarImportCount(count);
- AsmJsModuleInfo::ModuleVarImport varImport;
- for (int i = 0; i < count; i++)
- {
- current = ReadUInt32(current, &varImport.location);
- current = ReadByte(current, (byte*)&varImport.type);
- current = ReadInt32(current, &id);
- varImport.field = function->GetByteCodeCache()->LookupPropertyId(id);
- moduleInfo->SetVarImport(i, varImport);
- }
- current = ReadInt32(current, &count);
- moduleInfo->SetFunctionImportCount(count);
- AsmJsModuleInfo::ModuleFunctionImport funcImport;
- for (int i = 0; i < count; i++)
- {
- current = ReadUInt32(current, &funcImport.location);
- current = ReadInt32(current, &id);
- funcImport.field = function->GetByteCodeCache()->LookupPropertyId(id);
- moduleInfo->SetFunctionImport(i, funcImport);
- }
- current = ReadInt32(current, &count);
- moduleInfo->SetFunctionCount(count);
- AsmJsModuleInfo::ModuleFunction modFunc;
- for (int i = 0; i < count; i++)
- {
- current = ReadUInt32(current, &modFunc.location);
- moduleInfo->SetFunction(i, modFunc);
- }
- current = ReadInt32(current, &count);
- moduleInfo->SetFunctionTableCount(count);
- AsmJsModuleInfo::ModuleFunctionTable funcTable;
- for (int i = 0; i < count; i++)
- {
- current = ReadUInt32(current, &funcTable.size);
- if (funcTable.size > 0)
- {
- funcTable.moduleFunctionIndex = RecyclerNewArray(this->scriptContext->GetRecycler(), RegSlot, funcTable.size);
- }
- else
- {
- funcTable.moduleFunctionIndex = nullptr;
- }
- for (uint j = 0; j < funcTable.size; j++)
- {
- current = ReadConstantSizedInt32(current, (int32*)&funcTable.moduleFunctionIndex[j]);
- }
- moduleInfo->SetFunctionTable(i, funcTable);
- }
- serialization_alignment AsmJsModuleMemory * modMem = (serialization_alignment AsmJsModuleMemory*)current;
- moduleInfo->SetModuleMemory(*modMem);
- current = current + sizeof(serialization_alignment AsmJsModuleMemory);
- current = ReadInt32(current, &count);
- for (int i = 0; i < count; i++)
- {
- current = ReadInt32(current, &id);
- PropertyId key = function->GetByteCodeCache()->LookupPropertyId(id);
- serialization_alignment AsmJsSlot * slot = (serialization_alignment AsmJsSlot*)current;
- current = current + sizeof(serialization_alignment AsmJsSlot);
- // copy the slot to recycler memory
- AsmJsSlot * recyclerSlot = RecyclerNew(scriptContext->GetRecycler(), AsmJsSlot);
- *recyclerSlot = *slot;
- moduleInfo->GetAsmJsSlotMap()->Add(key, recyclerSlot);
- }
- serialization_alignment BVStatic<ASMMATH_BUILTIN_SIZE> * mathBV = (serialization_alignment BVStatic<ASMMATH_BUILTIN_SIZE>*)current;
- current = current + sizeof(serialization_alignment BVStatic<ASMMATH_BUILTIN_SIZE>);
- moduleInfo->SetAsmMathBuiltinUsed(*mathBV);
- serialization_alignment BVStatic<ASMARRAY_BUILTIN_SIZE> * arrayBV = (serialization_alignment BVStatic<ASMARRAY_BUILTIN_SIZE>*)current;
- current = current + sizeof(serialization_alignment BVStatic<ASMARRAY_BUILTIN_SIZE>);
- moduleInfo->SetAsmArrayBuiltinUsed(*arrayBV);
- uint maxAccess;
- current = ReadUInt32(current, &maxAccess);
- moduleInfo->SetMaxHeapAccess(maxAccess);
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- current = ReadInt32(current, &constant);
- Assert(constant == magicEndOfAsmJsModuleInfo);
- #endif
- return current;
- }
- #endif
- // Read a function body
- HRESULT ReadFunctionBody(const byte * functionBytes, FunctionProxy ** functionProxy, Utf8SourceInfo* sourceInfo, ByteCodeCache * cache, NativeModule *nativeModule, bool deserializeThis, bool deserializeNested = true, Js::DeferDeserializeFunctionInfo* deferDeserializeFunctionInfo = NULL)
- {
- Assert(sourceInfo->GetSrcInfo()->moduleID == kmodGlobal);
- int displayNameId;
- int lineNumber;
- int columnNumber;
- unsigned int bitflags;
- const byte * current = this->ReadFunctionBodyHeader(functionBytes, displayNameId, lineNumber, columnNumber, bitflags);
- serialization_alignment SerializedFieldList* definedFields = (serialization_alignment SerializedFieldList*) functionBytes;
- FunctionProxy::SetDisplayNameFlags displayNameFlags = FunctionProxy::SetDisplayNameFlags::SetDisplayNameFlagsDontCopy;
- const char16* displayName = nullptr;
- if (bitflags & ffIsAnonymous)
- {
- displayName = Constants::AnonymousFunction;
- }
- else
- {
- if (deferDeserializeFunctionInfo != nullptr)
- {
- displayName = deferDeserializeFunctionInfo->GetDisplayName();
- if (deferDeserializeFunctionInfo->GetDisplayNameIsRecyclerAllocated())
- {
- displayNameFlags = (FunctionProxy::SetDisplayNameFlags)(displayNameFlags | FunctionProxy::SetDisplayNameFlags::SetDisplayNameFlagsRecyclerAllocated);
- }
- }
- else
- {
- displayName = GetString16ById(displayNameId);
- }
- }
- uint displayNameLength = (bitflags & ffIsAnonymous) ? Constants::AnonymousFunctionLength :
- deferDeserializeFunctionInfo ? deferDeserializeFunctionInfo->GetDisplayNameLength() :
- GetString16LengthById(displayNameId);
- uint displayShortNameOffset = deferDeserializeFunctionInfo ? deferDeserializeFunctionInfo->GetShortDisplayNameOffset() : 0;
- int functionId;
- current = ReadInt32(current, &functionId);
- int32 attributes = 0;
- if (definedFields->has_attributes)
- {
- current = ReadInt32(current, &attributes);
- }
- uint32 offsetIntoSource = 0;
- current = ReadUInt32(current, &offsetIntoSource);
- int nestedCount = 0;
- if (definedFields->has_m_nestedCount)
- {
- current = ReadInt32(current, &nestedCount);
- }
- bool isDeferredFunction = (attributes & FunctionInfo::Attributes::DeferredParse) != 0;
- Field(DeferredFunctionStub*) deferredStubs = nullptr;
- if (definedFields->has_deferredStubs)
- {
- Assert(isDeferredFunction);
- current = ReadDeferredStubs(current, nestedCount, &deferredStubs, true);
- }
- if (!deserializeThis && !isDeferredFunction)
- {
- Assert(sourceInfo->GetSrcInfo()->moduleID == kmodGlobal);
- Assert(!deserializeNested);
- *functionProxy = DeferDeserializeFunctionInfo::New(this->scriptContext, nestedCount, functionId, cache, functionBytes, sourceInfo, displayName, displayNameLength, displayShortNameOffset, nativeModule, (FunctionInfo::Attributes)attributes);
- return S_OK;
- }
- ParseableFunctionInfo **function = (ParseableFunctionInfo **) functionProxy;
- uint functionNumber;
- if (deferDeserializeFunctionInfo)
- {
- functionNumber = deferDeserializeFunctionInfo->GetFunctionNumber();
- }
- else
- {
- functionNumber = scriptContext->GetThreadContext()->NewFunctionNumber();
- }
- if (definedFields->has_ConstantCount)
- {
- FunctionBody **functionBody = (FunctionBody **) function;
- *functionBody = FunctionBody::NewFromRecycler(this->scriptContext, nullptr /*displayName*/, 0 /*displayNameLength*/, 0 /*displayShortNameOffset*/, nestedCount,
- sourceInfo,
- functionNumber,
- sourceInfo->GetSrcInfo()->sourceContextInfo->sourceContextId,
- firstFunctionId + functionId, (FunctionInfo::Attributes)attributes,
- Js::FunctionBody::FunctionBodyFlags::Flags_None // bytecode serializer will initialize
- #ifdef PERF_COUNTERS
- , (deferDeserializeFunctionInfo != nullptr)
- #endif
- );
- (*functionBody)->SetDisplayName(displayName, displayNameLength, displayShortNameOffset, displayNameFlags);
- Assert(!(*functionBody)->GetIsSerialized());
- (*functionBody)->SetByteCodeCache(cache);
- (*functionBody)->SetUtf8SourceInfo(utf8SourceInfo); // Set source info
- (*function)->m_utf8SourceHasBeenSet = true;
- }
- else
- {
- *function = ParseableFunctionInfo::New(this->scriptContext, nestedCount, firstFunctionId + functionId, utf8SourceInfo, displayName, displayNameLength, displayShortNameOffset, (FunctionInfo::Attributes)attributes,
- Js::FunctionBody::FunctionBodyFlags::Flags_None);
- }
- // These fields are manually deserialized previously
- (*function)->m_lineNumber = lineNumber;
- (*function)->m_columnNumber = columnNumber;
- (*function)->m_isDeclaration = (bitflags & ffIsDeclaration) ? true : false;
- (*function)->m_hasImplicitArgIns = (bitflags & ffHasImplicitArgsIn) ? true : false;
- (*function)->m_isAccessor = (bitflags & ffIsAccessor) ? true : false;
- (*function)->m_isStaticNameFunction = (bitflags & ffIsStaticNameFunction) ? true : false;
- (*function)->m_isNamedFunctionExpression = (bitflags & ffIsNamedFunctionExpression) ? true : false;
- (*function)->m_isNameIdentifierRef = (bitflags & ffIsNameIdentifierRef ) ? true : false;
- (*function)->m_isGlobalFunc = (bitflags & ffIsGlobalFunc) ? true : false;
- (*function)->m_dontInline = (bitflags & ffDontInline) ? true : false;
- (*function)->m_isStrictMode = (bitflags & ffIsStrictMode) ? true : false;
- (*function)->m_doBackendArgumentsOptimization = (bitflags & ffDoBackendArgumentsOptimization) ? true : false;
- (*function)->m_doScopeObjectCreation = (bitflags & ffDoScopeObjectCreation) ? true : false;
- (*function)->m_usesArgumentsObject = (bitflags & ffUsesArgumentsObject) ? true : false;
- (*function)->m_isEval = (bitflags & ffIsEval) ? true : false;
- (*function)->m_isDynamicFunction = (bitflags & ffIsDynamicFunction) ? true : false;
- // This is offsetIntoSource is the start offset in bytes as well.
- (*function)->m_cbStartOffset = (size_t) offsetIntoSource;
- (*function)->m_sourceIndex = this->sourceIndex;
- #define DEFINE_FUNCTION_PROXY_FIELDS 1
- #define DEFINE_PARSEABLE_FUNCTION_INFO_FIELDS 1
- #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
- if (definedFields->has_##name == true) { \
- current = Read##serializableType(current, &(*function)->##name); \
- }
- #include "SerializableFunctionFields.h"
- if (definedFields->has_ConstantCount)
- {
- FunctionBody **functionBody = (FunctionBody **)function;
- #define DEFINE_FUNCTION_BODY_FIELDS 1
- #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
- if (definedFields->has_##name == true) { \
- current = Read##serializableType(current, &(*functionBody)->##name); \
- }
- #define DECLARE_SERIALIZABLE_ACCESSOR_FIELD_NO_CHECK(type, name, serializableType) \
- type tmp##name=0; \
- current = Read##serializableType(current, &tmp##name); \
- (*functionBody)->Set##name##(tmp##name);
- #define DECLARE_SERIALIZABLE_ACCESSOR_FIELD(type, name, serializableType, defaultValue) \
- if (definedFields->has_##name == true) { \
- DECLARE_SERIALIZABLE_ACCESSOR_FIELD_NO_CHECK(type, name, serializableType); \
- }
- #include "SerializableFunctionFields.h"
- // TODO-STACK-NESTED-FUNC: Defer deserialize function doesn't have parent pointer, can't do stack nested func yet
- // The flags field is set to by default to Flags_HasNoExplicitReturnValue which means if it's serialized, the field will be set
- // 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
- // that here.
- if (definedFields->has_flags == false)
- {
- (*functionBody)->flags = FunctionBody::FunctionBodyFlags::Flags_None;
- }
- else
- {
- (*functionBody)->flags = (FunctionBody::FunctionBodyFlags)((*functionBody)->flags & ~FunctionBody::Flags_StackNestedFunc);
- }
- if (definedFields->has_m_envDepth == false)
- {
- (*functionBody)->m_envDepth = 0;
- }
- if (deserializeThis && !deserializeNested)
- {
- (*functionBody)->m_isPartialDeserializedFunction = true;
- }
- (*functionBody)->FinishSourceInfo(); // SourceInfo is complete. Register this functionBody to utf8SourceInfo.
- (*functionBody)->m_isFuncRegistered = (bitflags & ffIsFuncRegistered) ? true : false;
- (*functionBody)->m_hasAllNonLocalReferenced = (bitflags & ffhasAllNonLocalReferenced) ? true : false;
- (*functionBody)->m_hasSetIsObject = (bitflags & ffhasSetIsObject) ? true : false;
- (*functionBody)->m_CallsEval = (bitflags & ffhasSetCallsEval) ? true : false;
- (*functionBody)->m_ChildCallsEval = (bitflags & ffChildCallsEval) ? true : false;
- (*functionBody)->m_hasReferenceableBuiltInArguments = (bitflags & ffHasReferenceableBuiltInArguments) ? true : false;
- (*functionBody)->m_isParamAndBodyScopeMerged = (bitflags & ffIsParamAndBodyScopeMerged) ? true : false;
- #ifdef ASMJS_PLAT
- (*functionBody)->m_isAsmJsFunction = (bitflags & ffIsAsmJsFunction) ? true : false;
- (*functionBody)->m_isAsmjsMode = (bitflags & ffIsAsmJsMode) ? true : false;
- #endif
- if (definedFields->has_loopHeaderArray)
- {
- (*functionBody)->AllocateLoopHeaders();
- auto loopHeaderArray = (*functionBody)->GetLoopHeaderArray();
- uint loopCount = (*functionBody)->GetLoopCount();
- for (uint i = 0; i < loopCount; ++i)
- {
- uint startOffset, endOffset;
- current = ReadUInt32(current, &startOffset);
- current = ReadUInt32(current, &endOffset);
- loopHeaderArray[i].startOffset = startOffset;
- loopHeaderArray[i].endOffset = endOffset;
- }
- }
- #ifdef ASMJS_PLAT
- if (definedFields->has_asmJsInfo)
- {
- byte asmJsInfoKind;
- current = ReadByte(current, &asmJsInfoKind);
- if (asmJsInfoKind == 1)
- {
- current = ReadAsmJsFunctionInfo(current, *functionBody);
- }
- else if (asmJsInfoKind == 2)
- {
- current = ReadAsmJsModuleInfo(current, *functionBody);
- }
- else
- {
- Assert(false);
- }
- }
- #endif
- // Read constants table
- #ifdef ASMJS_PLAT
- if ((*functionBody)->GetIsAsmJsFunction())
- {
- current = ReadAsmJsConstantsTable(current, *functionBody);
- }
- else
- #endif
- {
- current = ReadConstantsTable(current, *functionBody);
- }
- // Byte code
- current = ReadByteBlock(current, [&functionBody, this](int contentLength, const byte* buffer)
- {
- if (contentLength == 0)
- {
- (*functionBody)->byteCodeBlock = nullptr;
- }
- else
- {
- // TODO: Abstract this out to ByteBlock::New
- (*functionBody)->byteCodeBlock = RecyclerNewLeaf(scriptContext->GetRecycler(), ByteBlock, contentLength, (byte*)buffer);
- }
- });
- // Auxiliary
- if (definedFields->has_auxiliary)
- {
- current = ReadAuxiliary(current, *functionBody);
- }
- if (definedFields->has_propertyIdOfFormals)
- {
- current = ReadPropertyIdOfFormals(current, *functionBody);
- }
- // Inline cache
- current = ReadCacheIdToPropertyIdMap(current, *functionBody);
- current = ReadReferencedPropertyIdMap(current, *functionBody);
- (*functionBody)->AllocateInlineCache();
- current = ReadPropertyIdsForScopeSlotArray(current, *functionBody);
- if (definedFields->has_slotIdInCachedScopeToNestedIndexArray)
- {
- current = ReadSlotIdInCachedScopeToNestedIndexArray(current, *functionBody);
- }
- if (definedFields->has_debuggerScopeSlotArray)
- {
- uint debuggerScopeCount = 0;
- current = ReadUInt32(current, &debuggerScopeCount);
- current = ReadSlotArrayDebuggerScopes(current, *functionBody, debuggerScopeCount);
- }
- (*functionBody)->AllocateObjectLiteralTypeArray();
- (*functionBody)->AllocateForInCache();
- // Literal regexes
- (*functionBody)->AllocateLiteralRegexArray();
- for (uint i = 0; i < (*functionBody)->GetLiteralRegexCount(); ++i)
- {
- int length;
- current = ReadInt32(current, &length);
- if (length == -1)
- {
- Assert(!(*functionBody)->GetLiteralRegex(i));
- continue;
- }
- int sourceId;
- current = ReadInt32(current, &sourceId);
- const auto source = GetString16ById(sourceId);
- UnifiedRegex::RegexFlags flags;
- CompileAssert(sizeof(flags) == sizeof(byte));
- current = ReadByte(current, reinterpret_cast<byte *>(&flags));
- (*functionBody)->SetLiteralRegex(i, RegexHelper::CompileDynamic(scriptContext, source, length, flags, true));
- }
- // Read source information
- current = ReadSmallSpanSequence(current, &(*functionBody)->m_sourceInfo.pSpanSequence);
- (*functionBody)->executionState.InitializeExecutionModeAndLimits(*functionBody);
- }
- // Read lexically nested functions
- if (nestedCount)
- {
- for(auto i = 0; i<nestedCount; ++i)
- {
- const byte * nestedFunctionBytes = nullptr;
- current = ReadOffsetAsPointer(current, &nestedFunctionBytes);
- if (nestedFunctionBytes == nullptr)
- {
- (*function)->SetNestedFunc(NULL, i, 0u);
- }
- else
- {
- FunctionProxy* nestedFunction = nullptr;
- // If we should deserialize nested functions, go ahead and do so
- // If we shouldn't, and we're currently deserializing a function proxy
- // that has been defer-deserialized, simply copy over the function proxy from
- // from the old function- otherwise, create proxies for the nested functions
- auto hr = ReadFunctionBody(nestedFunctionBytes, &nestedFunction, sourceInfo, cache, nativeModule, deserializeNested, deserializeNested);
- if (FAILED(hr))
- {
- Assert(0);
- return hr;
- }
- (*function)->SetNestedFunc(nestedFunction->GetFunctionInfo(), i, 0u);
- }
- }
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- // Magical ending
- int constant;
- ReadInt32(current, &constant);
- if (constant != magicEndOfFunctionBody)
- {
- Assert(constant == magicEndOfFunctionBody);
- Throw::FatalInternalError();
- }
- #endif
- if (definedFields->has_ConstantCount)
- {
- FunctionBody **functionBody = (FunctionBody **) function;
- #if DBG
- if (PHASE_DUMP(Js::DebuggerScopePhase, (*functionBody)))
- {
- (*functionBody)->DumpScopes();
- }
- #endif
- #if ENABLE_NATIVE_CODEGEN
- if ((!PHASE_OFF(Js::BackEndPhase, *functionBody))
- && !this->scriptContext->GetConfig()->IsNoNative()
- && !(*functionBody)->GetIsAsmjsMode())
- {
- GenerateFunction(this->scriptContext->GetNativeCodeGenerator(), *functionBody);
- }
- #endif // ENABLE_NATIVE_CODEGEN
- (*functionBody)->m_isPartialDeserializedFunction = false;
- }
- else if (!isDeferredFunction)
- {
- *function = (*function)->Parse(nullptr, true);
- }
- return S_OK;
- }
- const byte* ReadDeferredStubs(const byte* current, uint nestedCount, Field(DeferredFunctionStub*)* deferredStubs, bool recurse)
- {
- if (nestedCount == 0)
- {
- return current;
- }
- *deferredStubs = RecyclerNewArray(this->scriptContext->GetRecycler(), DeferredFunctionStub, nestedCount);
- for (uint i = 0; i < nestedCount; i++)
- {
- DeferredFunctionStub* nestedStub = *deferredStubs + i;
- current = ReadUInt32(current, &nestedStub->ichMin);
- current = ReadUInt32(current, (uint*)&nestedStub->fncFlags);
- serialization_alignment RestorePoint* restorePoint;
- current = ReadStruct<RestorePoint>(current, &restorePoint);
- nestedStub->restorePoint = *restorePoint;
- current = ReadUInt32(current, &nestedStub->capturedNameCount);
- nestedStub->capturedNameSerializedIds = RecyclerNewArray(this->scriptContext->GetRecycler(), int, nestedStub->capturedNameCount);
- for (uint j = 0; j < nestedStub->capturedNameCount; j++)
- {
- current = ReadInt32(current, &nestedStub->capturedNameSerializedIds[j]);
- }
- current = ReadUInt32(current, &nestedStub->nestedCount);
- if (recurse)
- {
- current = ReadDeferredStubs(current, nestedStub->nestedCount, &nestedStub->deferredStubs, recurse);
- }
- }
- return current;
- }
- // Read the top function body.
- HRESULT ReadTopFunctionBody(Field(FunctionBody*)* function, Utf8SourceInfo* sourceInfo, ByteCodeCache * cache, bool allowDefer, NativeModule *nativeModule)
- {
- auto topFunction = ReadInt32(functions, &functionCount);
- firstFunctionId = sourceInfo->GetSrcInfo()->sourceContextInfo->nextLocalFunctionId;
- // this needs to be addressed somehow...need to be able to merge sourcecontexts?
- // it looks like in chakra!Parser::ParseFncDecl, nextLocalFunctionId is what the next function number is, then it is incremented
- // so, if we start with a new/clean ID of 0, then add n to it, then the next
- //sourceInfo->GetSrcInfo()->sourceContextInfo->nextLocalFunctionId += functionCount * 2;
- sourceInfo->GetSrcInfo()->sourceContextInfo->nextLocalFunctionId += functionCount;
- sourceInfo->EnsureInitialized(functionCount);
- sourceInfo->GetSrcInfo()->sourceContextInfo->EnsureInitialized();
- #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_PREJIT)
- bool prejit = false;
- prejit = (!scriptContext->GetConfig()->IsNoNative() && Js::Configuration::Global.flags.Prejit && nativeModule == nullptr);
- allowDefer = allowDefer && !prejit;
- #endif
- FunctionBody* functionBody = NULL;
- auto result = ReadFunctionBody(topFunction, (FunctionProxy **)&functionBody, sourceInfo, cache, nativeModule, true, !allowDefer /* don't deserialize nested if defer is allowed */);
- (*function) = functionBody;
- sourceInfo->ClearTopLevelFunctionInfoList();
- sourceInfo->AddTopLevelFunctionInfo(functionBody->GetFunctionInfo(), this->scriptContext->GetRecycler());
- #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_PREJIT)
- if (prejit)
- {
- Assert(!allowDefer);
- GenerateAllFunctions(scriptContext->GetNativeCodeGenerator(), functionBody);
- }
- #endif
- return result;
- }
- // Deserialize and save a PropertyIdArray
- const byte *
- DeserializePropertyIdArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto, FunctionBody * functionBody)
- {
- auto serialized = (serialization_alignment const Js::SerializedPropertyIdArray *)buffer;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- Assert(serialized->magic == magicStartOfAuxPropIdArray);
- #endif
- auto propertyCount = serialized->propertyCount;
- auto extraSlotCount = serialized->extraSlots;
- Assert(serialized->offset + sizeof(PropertyIdArray) < deserializeInto->GetLength());
- auto result = (PropertyIdArray *)(deserializeInto->GetBuffer() + serialized->offset);
- result->count = propertyCount;
- result->extraSlots = extraSlotCount;
- Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
- result->hadDuplicates = serialized->hadDuplicates;
- result->has__proto__ = serialized->has__proto__;
- auto elements = (PropertyId*)(serialized + 1);
- for(int i=0;i<propertyCount;++i)
- {
- result->elements[i] = functionBody->GetByteCodeCache()->LookupPropertyId(elements[i]);
- }
- for(int i=0;i<extraSlotCount;++i)
- {
- result->elements[propertyCount + i] = elements[propertyCount + i];
- }
- auto current = buffer +
- sizeof(serialization_alignment const Js::SerializedPropertyIdArray) + (propertyCount + extraSlotCount) * sizeof(PropertyId);
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int magicEnd;
- current = ReadInt32(current, &magicEnd);
- Assert(magicEnd == magicEndOfAuxPropIdArray);
- #endif
- return current;
- }
- // Deserialize and save a FuncInfoArray
- const byte *
- DeserializeFuncInfoArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
- {
- auto serialized = (serialization_alignment const SerializedFuncInfoArray *)buffer;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- Assert(serialized->magic == magicStartOfAuxFuncInfoArray);
- #endif
- auto count = serialized->count;
- Assert(serialized->offset + sizeof(AuxArray<FuncInfoEntry>) < deserializeInto->GetLength());
- auto result = (AuxArray<FuncInfoEntry> *)(deserializeInto->GetBuffer() + serialized->offset);
- result->count = count;
- Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
- auto elements = (int*)(serialized+1);
- for(int i=0;i<count;++i)
- {
- result->elements[i].nestedIndex = elements[i*2];
- result->elements[i].scopeSlot = elements[i*2+1];
- }
- auto current = buffer + sizeof(serialization_alignment const SerializedFuncInfoArray) + (count * 2 * sizeof(int));
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int magicEnd;
- current = ReadInt32(current, &magicEnd);
- Assert(magicEnd == magicEndOfAuxFuncInfoArray);
- #endif
- return current;
- }
- // Deserialize a var array
- template<typename T>
- const byte * DeserializeVarArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
- {
- auto serialized = (serialization_alignment const Js::SerializedVarArray *)buffer;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- Assert(serialized->magic == magicStartOfAuxVarArray);
- #endif
- Assert(serialized->offset + sizeof(T) < deserializeInto->GetLength());
- auto result = (T *)(deserializeInto->GetBuffer() + serialized->offset);
- uint count = serialized->varCount;
- result->SetCount(count);
- Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
- auto content = (const byte*)(serialized + 1);
- auto current = content;
- for (uint index = 0; index < count; index++)
- {
- byte code;
- current = ReadByte(current, &code);
- switch(code)
- {
- case ctInt32:
- {
- int value;
- current = ReadConstantSizedInt32(current, &value);
- result->elements[index] = Js::TaggedInt::ToVarUnchecked(value);
- break;
- }
- case ctInt16:
- {
- int16 value;
- current = ReadConstantSizedInt16(current, &value);
- result->elements[index] = Js::TaggedInt::ToVarUnchecked(value);
- break;
- }
- case ctInt8:
- {
- int8 value;
- current = ReadByte(current, (byte *)&value);
- result->elements[index] = Js::TaggedInt::ToVarUnchecked(value);
- break;
- }
- case ctNumber:
- {
- double value;
- current = ReadDouble(current, &value);
- const auto number = Js::JavascriptNumber::New(value, scriptContext);
- #if !FLOATVAR
- scriptContext->BindReference(number);
- #endif
- result->elements[index] = number;
- break;
- }
- default:
- AssertMsg(UNREACHED, "Unexpected object type in VarArray");
- Throw::FatalInternalError();
- }
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int magicEnd;
- current = ReadInt32(current, &magicEnd);
- Assert(magicEnd == magicEndOfAuxVarArray);
- #endif
- return current;
- }
- const byte * DeserializeIntArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
- {
- auto serialized = (serialization_alignment const Js::SerializedIntArray *)buffer;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- Assert(serialized->magic == magicStartOfAuxIntArray);
- #endif
- Assert(serialized->offset + sizeof(AuxArray<int>) < deserializeInto->GetLength());
- auto result = (AuxArray<int> *)(deserializeInto->GetBuffer() + serialized->offset);
- uint count = serialized->intCount;
- result->count = count;
- Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
- auto content = (const byte*)(serialized + 1);
- auto current = content;
- for (uint index = 0; index < count; index++)
- {
- int32 value;
- current = ReadConstantSizedInt32(current, &value);
- result->elements[index] = value;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int magicEnd;
- current = ReadInt32(current, &magicEnd);
- Assert(magicEnd == magicEndOfAuxIntArray);
- #endif
- return current;
- }
- const byte *
- DeserializeFloatArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
- {
- auto serialized = (serialization_alignment const SerializedFloatArray *)buffer;
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- Assert(serialized->magic == magicStartOfAuxFltArray);
- #endif
- Assert(serialized->offset + sizeof(AuxArray<double>) < deserializeInto->GetLength());
- auto result = (AuxArray<double> *)(deserializeInto->GetBuffer() + serialized->offset);
- uint count = serialized->floatCount;
- result->count = count;
- Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
- auto content = (const byte*)(serialized + 1);
- auto current = content;
- for (uint index = 0; index < count; index++)
- {
- double value;
- current = ReadDouble(current, &value);
- result->elements[index] = value;
- }
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- int magicEnd;
- current = ReadInt32(current, &magicEnd);
- Assert(magicEnd == magicEndOfAuxFltArray);
- #endif
- return current;
- }
- };
- // Construct the byte code cache. Copy things needed by inline 'Lookup' functions from reader.
- ByteCodeCache::ByteCodeCache(ScriptContext * scriptContext, ByteCodeBufferReader * reader, int builtInPropertyCount)
- : reader(reader), propertyCount(reader->string16Count), builtInPropertyCount(builtInPropertyCount)
- {
- auto alloc = scriptContext->SourceCodeAllocator();
- propertyIds = AnewArray(alloc, PropertyId, propertyCount);
- for (auto i=0; i < propertyCount; ++i)
- {
- propertyIds[i] = -1;
- }
- raw = reader->raw;
- // Read and populate PropertyIds
- for(int i=0; i < propertyCount; ++i)
- {
- PopulateLookupPropertyId(scriptContext, i);
- }
- }
- // Deserialize and save a PropertyId
- void ByteCodeCache::PopulateLookupPropertyId(ScriptContext * scriptContext, int realOffset)
- {
- PropertyId idInCache = realOffset + this->builtInPropertyCount;
- bool isPropertyRecord;
- auto propertyName = reader->GetString16ById(idInCache, &isPropertyRecord);
- if(isPropertyRecord)
- {
- auto propertyNameLength = reader->GetString16LengthById(idInCache);
- const Js::PropertyRecord * propertyRecord = scriptContext->GetThreadContext()->GetOrAddPropertyRecordBind(
- JsUtil::CharacterBuffer<char16>(propertyName, propertyNameLength));
- propertyIds[realOffset] = propertyRecord->GetPropertyId();
- }
- }
- // Serialize function body
- HRESULT ByteCodeSerializer::SerializeToBuffer(ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD sourceByteLength, LPCUTF8 utf8Source, FunctionBody * function, SRCINFO const* srcInfo, bool allocateBuffer, byte ** buffer, DWORD * bufferBytes, DWORD dwFlags)
- {
- int builtInPropertyCount = (dwFlags & GENERATE_BYTE_CODE_BUFFER_LIBRARY) != 0 ? PropertyIds::_countJSOnlyProperty : TotalNumberOfBuiltInProperties;
- Utf8SourceInfo *utf8SourceInfo = function->GetUtf8SourceInfo();
- HRESULT hr = utf8SourceInfo->EnsureLineOffsetCacheNoThrow();
- if (FAILED(hr))
- {
- return hr;
- }
- int32 sourceCharLength = utf8SourceInfo->GetCchLength();
- ByteCodeBufferBuilder builder(sourceByteLength, sourceCharLength, utf8Source, utf8SourceInfo, scriptContext, alloc, dwFlags, builtInPropertyCount);
-
- hr = builder.AddTopFunctionBody(function, srcInfo);
- if (SUCCEEDED(hr))
- {
- hr = builder.Create(allocateBuffer, buffer, bufferBytes);
- }
- #if INSTRUMENT_BUFFER_INTS
- for (int i = 0; i < 4; i++)
- {
- Output::Print(_u("[BCGENSTATS] %d, %d\n"), i, Counts[i]);
- }
- #endif
- return hr;
- }
- HRESULT ByteCodeSerializer::DeserializeFromBuffer(ScriptContext * scriptContext, uint32 scriptFlags, LPCUTF8 utf8Source, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex)
- {
- return ByteCodeSerializer::DeserializeFromBufferInternal(scriptContext, scriptFlags, utf8Source, /* sourceHolder */ nullptr, srcInfo, buffer, nativeModule, function, sourceIndex);
- }
- // Deserialize function body from supplied buffer
- HRESULT ByteCodeSerializer::DeserializeFromBuffer(ScriptContext * scriptContext, uint32 scriptFlags, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex)
- {
- AssertMsg(sourceHolder != nullptr || sourceIndex != Js::Constants::InvalidSourceIndex, "SourceHolder can't be null, if you have an empty source then pass ISourceHolder::GetEmptySourceHolder()");
- return ByteCodeSerializer::DeserializeFromBufferInternal(scriptContext, scriptFlags, /* utf8Source */ nullptr, sourceHolder, srcInfo, buffer, nativeModule, function, sourceIndex);
- }
- HRESULT ByteCodeSerializer::DeserializeFromBufferInternal(ScriptContext * scriptContext, uint32 scriptFlags, LPCUTF8 utf8Source, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex)
- {
- //ETW Event start
- JS_ETW(EventWriteJSCRIPT_BYTECODEDESERIALIZE_START(scriptContext, 0));
- auto alloc = scriptContext->SourceCodeAllocator();
- bool isLibraryCode = ((scriptFlags & fscrIsLibraryCode) == fscrIsLibraryCode);
- bool isJsBuiltInCode = ((scriptFlags & fscrJsBuiltIn) == fscrJsBuiltIn);
- bool isLibraryOrJsBuiltInCode = isLibraryCode || isJsBuiltInCode;
- int builtInPropertyCount = isLibraryOrJsBuiltInCode ? PropertyIds::_countJSOnlyProperty : TotalNumberOfBuiltInProperties;
- auto reader = Anew(alloc, ByteCodeBufferReader, scriptContext, buffer, isLibraryOrJsBuiltInCode, builtInPropertyCount);
- auto hr = reader->ReadHeader();
- if (FAILED(hr))
- {
- return hr;
- }
- ENTER_PINNED_SCOPE(Js::Utf8SourceInfo, sourceInfo);
- ENTER_PINNED_SCOPE(SRCINFO const, pinnedSrcInfo);
- pinnedSrcInfo = srcInfo;
- if(sourceIndex == Js::Constants::InvalidSourceIndex)
- {
- if (sourceHolder == nullptr)
- {
- sourceHolder = utf8Source == nullptr ? ISourceHolder::GetEmptySourceHolder() : RecyclerNew(scriptContext->GetRecycler(), SimpleSourceHolder, utf8Source, reader->sourceSize);
- }
- sourceInfo = Js::Utf8SourceInfo::NewWithHolder(scriptContext, sourceHolder,
- reader->sourceCharLength, pinnedSrcInfo, isLibraryOrJsBuiltInCode);
- reader->utf8SourceInfo = sourceInfo;
- reader->sourceIndex = scriptContext->SaveSourceNoCopy(sourceInfo, reader->sourceCharLength, false);
- sourceInfo->CreateLineOffsetCache(reader->lineCharacterOffsetCacheBuffer, reader->lineByteOffsetCacheBuffer, reader->lineInfoCacheCount);
- }
- else
- {
- Assert(CONFIG_FLAG(ForceSerialized) || ((scriptFlags & fscrCreateParserState) == fscrCreateParserState));
- sourceInfo = scriptContext->GetSource(sourceIndex);
- reader->utf8SourceInfo = sourceInfo;
- reader->sourceIndex = sourceIndex;
- }
- auto cache = Anew(alloc, ByteCodeCache, scriptContext, reader, builtInPropertyCount);
- hr = reader->ReadTopFunctionBody(function, sourceInfo, cache, ((scriptFlags & fscrAllowFunctionProxy) == fscrAllowFunctionProxy), nativeModule);
- //ETW Event stop
- JS_ETW(EventWriteJSCRIPT_BYTECODEDESERIALIZE_STOP(scriptContext,0));
- LEAVE_PINNED_SCOPE();
- LEAVE_PINNED_SCOPE();
- return hr;
- }
- void ByteCodeSerializer::ReadSourceInfo(const DeferDeserializeFunctionInfo* deferredFunction, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction)
- {
- ByteCodeCache* cache = deferredFunction->m_cache;
- ByteCodeBufferReader* reader = cache->GetReader();
- reader->ReadSourceInfo(deferredFunction->m_functionBytes, lineNumber, columnNumber, m_isEval, m_isDynamicFunction);
- }
- FunctionBody* ByteCodeSerializer::DeserializeFunction(ScriptContext* scriptContext, DeferDeserializeFunctionInfo* deferredFunction)
- {
- FunctionBody* deserializedFunctionBody = nullptr;
- ByteCodeCache* cache = deferredFunction->m_cache;
- ByteCodeBufferReader* reader = cache->GetReader();
- HRESULT hr = reader->ReadFunctionBody(deferredFunction->m_functionBytes, (FunctionProxy **)&deserializedFunctionBody, deferredFunction->GetUtf8SourceInfo(), cache, deferredFunction->m_nativeModule, true /* deserialize this */, false /* deserialize nested functions */, deferredFunction);
- if (FAILED(hr))
- {
- // This should never happen as the code is currently
- // structured since we validate the serialized bytecode during creation
- // of function proxies. In the future though, when we reorganize the byte
- // code file format, we could hit this error, in which case we
- // need a strategy to deal with this.
- Assert(false);
- Js::Throw::InternalError();
- }
- return deserializedFunctionBody;
- }
- SerializedAuxiliary::SerializedAuxiliary( uint offset, SerializedAuxiliaryKind kind ) :
- offset(offset), kind(kind)
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- , auxMagic(magicStartOfAux)
- #endif
- {
- }
- SerializedVarArray::SerializedVarArray( uint offset, bool isVarCount, int varCount ) :
- SerializedAuxiliary(offset, isVarCount ? sakVarArrayVarCount : sakVarArrayIntCount), varCount(varCount)
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- , magic(magicStartOfAuxVarArray)
- #endif
- {
- }
- SerializedIntArray::SerializedIntArray( uint offset, int intCount ) :
- SerializedAuxiliary(offset, sakIntArray), intCount(intCount)
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- , magic(magicStartOfAuxIntArray)
- #endif
- {
- }
- SerializedFloatArray::SerializedFloatArray( uint offset, int floatCount ) :
- SerializedAuxiliary(offset, sakFloatArray), floatCount(floatCount)
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- , magic(magicStartOfAuxFltArray)
- #endif
- {
- }
- SerializedPropertyIdArray::SerializedPropertyIdArray( uint offset, int propertyCount, byte extraSlots, bool hadDuplicates, bool has__proto__) :
- SerializedAuxiliary(offset, sakPropertyIdArray), propertyCount(propertyCount), extraSlots(extraSlots), hadDuplicates(hadDuplicates), has__proto__(has__proto__)
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- , magic(magicStartOfAuxPropIdArray)
- #endif
- {
- }
- SerializedFuncInfoArray::SerializedFuncInfoArray( uint offset, int count ) :
- SerializedAuxiliary(offset, sakFuncInfoArray), count(count)
- #ifdef BYTE_CODE_MAGIC_CONSTANTS
- , magic(magicStartOfAuxFuncInfoArray)
- #endif
- {
- }
- } // namespace Js
|