ByteCodeGenerator.cpp 187 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeByteCodePch.h"
  6. #include "FormalsUtil.h"
  7. #include "Library\StackScriptFunction.h"
  8. void PreVisitBlock(ParseNode *pnodeBlock, ByteCodeGenerator *byteCodeGenerator);
  9. void PostVisitBlock(ParseNode *pnodeBlock, ByteCodeGenerator *byteCodeGenerator);
  10. bool IsCallOfConstants(ParseNode *pnode)
  11. {
  12. return pnode->sxCall.callOfConstants && pnode->sxCall.argCount > ByteCodeGenerator::MinArgumentsForCallOptimization;
  13. }
  14. template <class PrefixFn, class PostfixFn>
  15. void Visit(ParseNode *pnode, ByteCodeGenerator* byteCodeGenerator, PrefixFn prefix, PostfixFn postfix, ParseNode * pnodeParent = nullptr);
  16. template<class TContext>
  17. void VisitIndirect(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, TContext* context,
  18. void (*prefix)(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, TContext* context),
  19. void (*postfix)(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, TContext* context),
  20. ParseNode *pnodeParent = nullptr)
  21. {
  22. Visit(pnode, byteCodeGenerator,
  23. [context, prefix](ParseNode * pnode, ByteCodeGenerator * byteCodeGenerator)
  24. {
  25. prefix(pnode, byteCodeGenerator, context);
  26. },
  27. [context, postfix](ParseNode * pnode, ByteCodeGenerator * byteCodeGenerator)
  28. {
  29. if (postfix)
  30. {
  31. postfix(pnode, byteCodeGenerator, context);
  32. }
  33. }, pnodeParent);
  34. }
  35. template <class PrefixFn, class PostfixFn>
  36. void VisitList(ParseNode *pnode, ByteCodeGenerator* byteCodeGenerator, PrefixFn prefix, PostfixFn postfix)
  37. {
  38. Assert(pnode != nullptr);
  39. Assert(pnode->nop == knopList);
  40. do
  41. {
  42. ParseNode * pnode1 = pnode->sxBin.pnode1;
  43. Visit(pnode1, byteCodeGenerator, prefix, postfix);
  44. pnode = pnode->sxBin.pnode2;
  45. }
  46. while (pnode->nop == knopList);
  47. Visit(pnode, byteCodeGenerator, prefix, postfix);
  48. }
  49. template <class PrefixFn, class PostfixFn>
  50. void VisitWithStmt(ParseNode *pnode, Js::RegSlot loc, ByteCodeGenerator* byteCodeGenerator, PrefixFn prefix, PostfixFn postfix, ParseNode *pnodeParent)
  51. {
  52. // Note the fact that we're visiting the body of a with statement. This allows us to optimize register assignment
  53. // in the normal case of calls not requiring that their "this" objects be found dynamically.
  54. Scope *scope = pnode->sxWith.scope;
  55. byteCodeGenerator->PushScope(scope);
  56. Visit(pnode->sxWith.pnodeBody, byteCodeGenerator, prefix, postfix, pnodeParent);
  57. scope->SetIsObject();
  58. scope->SetMustInstantiate(true);
  59. byteCodeGenerator->PopScope();
  60. }
  61. bool BlockHasOwnScope(ParseNode* pnodeBlock, ByteCodeGenerator *byteCodeGenerator)
  62. {
  63. Assert(pnodeBlock->nop == knopBlock);
  64. return pnodeBlock->sxBlock.scope != nullptr &&
  65. (!(pnodeBlock->grfpn & fpnSyntheticNode) ||
  66. (pnodeBlock->sxBlock.blockType == PnodeBlockType::Global && byteCodeGenerator->IsEvalWithBlockScopingNoParentScopeInfo()));
  67. }
  68. void BeginVisitBlock(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  69. {
  70. if (BlockHasOwnScope(pnode, byteCodeGenerator))
  71. {
  72. Scope *scope = pnode->sxBlock.scope;
  73. FuncInfo *func = scope->GetFunc();
  74. if (scope->IsInnerScope())
  75. {
  76. // Give this scope an index so its slots can be accessed via the index in the byte code,
  77. // not a register.
  78. scope->SetInnerScopeIndex(func->AcquireInnerScopeIndex());
  79. }
  80. byteCodeGenerator->PushBlock(pnode);
  81. byteCodeGenerator->PushScope(pnode->sxBlock.scope);
  82. }
  83. }
  84. void EndVisitBlock(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  85. {
  86. if (BlockHasOwnScope(pnode, byteCodeGenerator))
  87. {
  88. Scope *scope = pnode->sxBlock.scope;
  89. FuncInfo *func = scope->GetFunc();
  90. if (!byteCodeGenerator->IsInDebugMode() &&
  91. scope->HasInnerScopeIndex())
  92. {
  93. // In debug mode, don't release the current index, as we're giving each scope a unique index, regardless
  94. // of nesting.
  95. Assert(scope->GetInnerScopeIndex() == func->CurrentInnerScopeIndex());
  96. func->ReleaseInnerScopeIndex();
  97. }
  98. Assert(byteCodeGenerator->GetCurrentScope() == scope);
  99. byteCodeGenerator->PopScope();
  100. byteCodeGenerator->PopBlock();
  101. }
  102. }
  103. void BeginVisitCatch(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  104. {
  105. Scope *scope = pnode->sxCatch.scope;
  106. FuncInfo *func = scope->GetFunc();
  107. if (func->GetCallsEval() || func->GetChildCallsEval() ||
  108. (byteCodeGenerator->GetFlags() & (fscrEval | fscrImplicitThis | fscrImplicitParents)))
  109. {
  110. scope->SetIsObject();
  111. }
  112. // Give this scope an index so its slots can be accessed via the index in the byte code,
  113. // not a register.
  114. scope->SetInnerScopeIndex(func->AcquireInnerScopeIndex());
  115. byteCodeGenerator->PushScope(pnode->sxCatch.scope);
  116. }
  117. void EndVisitCatch(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  118. {
  119. Scope *scope = pnode->sxCatch.scope;
  120. if (scope->HasInnerScopeIndex() && !byteCodeGenerator->IsInDebugMode())
  121. {
  122. // In debug mode, don't release the current index, as we're giving each scope a unique index,
  123. // regardless of nesting.
  124. FuncInfo *func = scope->GetFunc();
  125. Assert(scope->GetInnerScopeIndex() == func->CurrentInnerScopeIndex());
  126. func->ReleaseInnerScopeIndex();
  127. }
  128. byteCodeGenerator->PopScope();
  129. }
  130. bool CreateNativeArrays(ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo)
  131. {
  132. #if ENABLE_PROFILE_INFO
  133. Js::FunctionBody *functionBody = funcInfo ? funcInfo->GetParsedFunctionBody() : nullptr;
  134. return
  135. !PHASE_OFF_OPTFUNC(Js::NativeArrayPhase, functionBody) &&
  136. !byteCodeGenerator->IsInDebugMode() &&
  137. (
  138. functionBody
  139. ? Js::DynamicProfileInfo::IsEnabled(Js::NativeArrayPhase, functionBody)
  140. : Js::DynamicProfileInfo::IsEnabledForAtLeastOneFunction(
  141. Js::NativeArrayPhase,
  142. byteCodeGenerator->GetScriptContext())
  143. );
  144. #else
  145. return false;
  146. #endif
  147. }
  148. bool EmitAsConstantArray(ParseNode *pnodeArr, ByteCodeGenerator *byteCodeGenerator)
  149. {
  150. Assert(pnodeArr && pnodeArr->nop == knopArray);
  151. // TODO: We shouldn't have to handle an empty funcinfo stack here, but there seem to be issues
  152. // with the stack involved nested deferral. Remove this null check when those are resolved.
  153. if (CreateNativeArrays(byteCodeGenerator, byteCodeGenerator->TopFuncInfo()))
  154. {
  155. return pnodeArr->sxArrLit.arrayOfNumbers;
  156. }
  157. return pnodeArr->sxArrLit.arrayOfTaggedInts && pnodeArr->sxArrLit.count > 1;
  158. }
  159. void PropagateFlags(ParseNode *pnodeChild, ParseNode *pnodeParent);
  160. template<class PrefixFn, class PostfixFn>
  161. void Visit(ParseNode *pnode, ByteCodeGenerator* byteCodeGenerator, PrefixFn prefix, PostfixFn postfix, ParseNode *pnodeParent)
  162. {
  163. if (pnode == nullptr)
  164. {
  165. return;
  166. }
  167. ThreadContext::ProbeCurrentStackNoDispose(Js::Constants::MinStackByteCodeVisitor, byteCodeGenerator->GetScriptContext());
  168. prefix(pnode, byteCodeGenerator);
  169. switch (pnode->nop)
  170. {
  171. default:
  172. {
  173. uint flags = ParseNode::Grfnop(pnode->nop);
  174. if (flags&fnopUni)
  175. {
  176. Visit(pnode->sxUni.pnode1, byteCodeGenerator, prefix, postfix);
  177. }
  178. else if (flags&fnopBin)
  179. {
  180. Visit(pnode->sxBin.pnode1, byteCodeGenerator, prefix, postfix);
  181. Visit(pnode->sxBin.pnode2, byteCodeGenerator, prefix, postfix);
  182. }
  183. break;
  184. }
  185. case knopParamPattern:
  186. Visit(pnode->sxParamPattern.pnode1, byteCodeGenerator, prefix, postfix);
  187. break;
  188. case knopArrayPattern:
  189. if (!byteCodeGenerator->InDestructuredPattern())
  190. {
  191. byteCodeGenerator->SetInDestructuredPattern(true);
  192. Visit(pnode->sxUni.pnode1, byteCodeGenerator, prefix, postfix);
  193. byteCodeGenerator->SetInDestructuredPattern(false);
  194. }
  195. else
  196. {
  197. Visit(pnode->sxUni.pnode1, byteCodeGenerator, prefix, postfix);
  198. }
  199. break;
  200. case knopCall:
  201. Visit(pnode->sxCall.pnodeTarget, byteCodeGenerator, prefix, postfix);
  202. Visit(pnode->sxCall.pnodeArgs, byteCodeGenerator, prefix, postfix);
  203. break;
  204. case knopNew:
  205. {
  206. Visit(pnode->sxCall.pnodeTarget, byteCodeGenerator, prefix, postfix);
  207. if (!IsCallOfConstants(pnode))
  208. {
  209. Visit(pnode->sxCall.pnodeArgs, byteCodeGenerator, prefix, postfix);
  210. }
  211. break;
  212. }
  213. case knopQmark:
  214. Visit(pnode->sxTri.pnode1, byteCodeGenerator, prefix, postfix);
  215. Visit(pnode->sxTri.pnode2, byteCodeGenerator, prefix, postfix);
  216. Visit(pnode->sxTri.pnode3, byteCodeGenerator, prefix, postfix);
  217. break;
  218. case knopList:
  219. VisitList(pnode, byteCodeGenerator, prefix, postfix);
  220. break;
  221. // PTNODE(knopVarDecl , "varDcl" ,None ,Var ,fnopNone)
  222. case knopVarDecl:
  223. case knopConstDecl:
  224. case knopLetDecl:
  225. if (pnode->sxVar.pnodeInit != nullptr)
  226. Visit(pnode->sxVar.pnodeInit, byteCodeGenerator, prefix, postfix);
  227. break;
  228. // PTNODE(knopFncDecl , "fncDcl" ,None ,Fnc ,fnopLeaf)
  229. case knopFncDecl:
  230. {
  231. // Inner function declarations are visited before anything else in the scope.
  232. // (See VisitFunctionsInScope.)
  233. break;
  234. }
  235. case knopClassDecl:
  236. {
  237. // Visit the extends expression first, since it's bound outside the scope containing the class name.
  238. Visit(pnode->sxClass.pnodeExtends, byteCodeGenerator, prefix, postfix);
  239. Visit(pnode->sxClass.pnodeDeclName, byteCodeGenerator, prefix, postfix);
  240. // Now visit the class name and methods.
  241. BeginVisitBlock(pnode->sxClass.pnodeBlock, byteCodeGenerator);
  242. Visit(pnode->sxClass.pnodeName, byteCodeGenerator, prefix, postfix);
  243. Visit(pnode->sxClass.pnodeStaticMembers, byteCodeGenerator, prefix, postfix);
  244. Visit(pnode->sxClass.pnodeConstructor, byteCodeGenerator, prefix, postfix);
  245. Visit(pnode->sxClass.pnodeMembers, byteCodeGenerator, prefix, postfix);
  246. EndVisitBlock(pnode->sxClass.pnodeBlock, byteCodeGenerator);
  247. break;
  248. }
  249. case knopStrTemplate:
  250. {
  251. // Visit the string node lists only if we do not have a tagged template.
  252. // We never need to visit the raw strings as they are not used in non-tagged templates and
  253. // tagged templates will register them as part of the callsite constant object.
  254. if (!pnode->sxStrTemplate.isTaggedTemplate)
  255. {
  256. Visit(pnode->sxStrTemplate.pnodeStringLiterals, byteCodeGenerator, prefix, postfix);
  257. }
  258. Visit(pnode->sxStrTemplate.pnodeSubstitutionExpressions, byteCodeGenerator, prefix, postfix);
  259. break;
  260. }
  261. // PTNODE(knopProg , "program" ,None ,Fnc ,fnopNone)
  262. case knopProg:
  263. {
  264. // We expect that the global statements have been generated (meaning that the pnodeFncs
  265. // field is a real pointer, not an enumeration).
  266. Assert(pnode->sxFnc.pnodeBody);
  267. uint i = 0;
  268. VisitNestedScopes(pnode->sxFnc.pnodeScopes, pnode, byteCodeGenerator, prefix, postfix, &i);
  269. // Visiting global code: track the last value statement.
  270. BeginVisitBlock(pnode->sxFnc.pnodeScopes, byteCodeGenerator);
  271. pnode->sxProg.pnodeLastValStmt = VisitBlock(pnode->sxFnc.pnodeBody, byteCodeGenerator, prefix, postfix);
  272. EndVisitBlock(pnode->sxFnc.pnodeScopes, byteCodeGenerator);
  273. break;
  274. }
  275. case knopFor:
  276. BeginVisitBlock(pnode->sxFor.pnodeBlock, byteCodeGenerator);
  277. Visit(pnode->sxFor.pnodeInit, byteCodeGenerator, prefix, postfix);
  278. byteCodeGenerator->EnterLoop();
  279. Visit(pnode->sxFor.pnodeCond, byteCodeGenerator, prefix, postfix);
  280. Visit(pnode->sxFor.pnodeIncr, byteCodeGenerator, prefix, postfix);
  281. Visit(pnode->sxFor.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  282. byteCodeGenerator->ExitLoop();
  283. EndVisitBlock(pnode->sxFor.pnodeBlock, byteCodeGenerator);
  284. break;
  285. // PTNODE(knopIf , "if" ,None ,If ,fnopNone)
  286. case knopIf:
  287. Visit(pnode->sxIf.pnodeCond, byteCodeGenerator, prefix, postfix);
  288. Visit(pnode->sxIf.pnodeTrue, byteCodeGenerator, prefix, postfix, pnode);
  289. if (pnode->sxIf.pnodeFalse != nullptr)
  290. {
  291. Visit(pnode->sxIf.pnodeFalse, byteCodeGenerator, prefix, postfix, pnode);
  292. }
  293. break;
  294. // PTNODE(knopWhile , "while" ,None ,While,fnopBreak|fnopContinue)
  295. // PTNODE(knopDoWhile , "do-while" ,None ,While,fnopBreak|fnopContinue)
  296. case knopDoWhile:
  297. case knopWhile:
  298. byteCodeGenerator->EnterLoop();
  299. Visit(pnode->sxWhile.pnodeCond, byteCodeGenerator, prefix, postfix);
  300. Visit(pnode->sxWhile.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  301. byteCodeGenerator->ExitLoop();
  302. break;
  303. // PTNODE(knopForIn , "for in" ,None ,ForIn,fnopBreak|fnopContinue|fnopCleanup)
  304. case knopForIn:
  305. case knopForOf:
  306. BeginVisitBlock(pnode->sxForInOrForOf.pnodeBlock, byteCodeGenerator);
  307. Visit(pnode->sxForInOrForOf.pnodeLval, byteCodeGenerator, prefix, postfix);
  308. Visit(pnode->sxForInOrForOf.pnodeObj, byteCodeGenerator, prefix, postfix);
  309. byteCodeGenerator->EnterLoop();
  310. Visit(pnode->sxForInOrForOf.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  311. byteCodeGenerator->ExitLoop();
  312. EndVisitBlock(pnode->sxForInOrForOf.pnodeBlock, byteCodeGenerator);
  313. break;
  314. // PTNODE(knopReturn , "return" ,None ,Uni ,fnopNone)
  315. case knopReturn:
  316. if (pnode->sxReturn.pnodeExpr != nullptr)
  317. Visit(pnode->sxReturn.pnodeExpr, byteCodeGenerator, prefix, postfix);
  318. break;
  319. // PTNODE(knopBlock , "{}" ,None ,Block,fnopNone)
  320. case knopBlock:
  321. {
  322. if (pnode->sxBlock.pnodeStmt != nullptr)
  323. {
  324. BeginVisitBlock(pnode, byteCodeGenerator);
  325. pnode->sxBlock.pnodeLastValStmt = VisitBlock(pnode->sxBlock.pnodeStmt, byteCodeGenerator, prefix, postfix, pnode);
  326. EndVisitBlock(pnode, byteCodeGenerator);
  327. }
  328. else
  329. {
  330. pnode->sxBlock.pnodeLastValStmt = nullptr;
  331. }
  332. break;
  333. }
  334. // PTNODE(knopWith , "with" ,None ,With ,fnopCleanup)
  335. case knopWith:
  336. Visit(pnode->sxWith.pnodeObj, byteCodeGenerator, prefix, postfix);
  337. VisitWithStmt(pnode, pnode->sxWith.pnodeObj->location, byteCodeGenerator, prefix, postfix, pnode);
  338. break;
  339. // PTNODE(knopBreak , "break" ,None ,Jump ,fnopNone)
  340. case knopBreak:
  341. // TODO: some representation of target
  342. break;
  343. // PTNODE(knopContinue , "continue" ,None ,Jump ,fnopNone)
  344. case knopContinue:
  345. // TODO: some representation of target
  346. break;
  347. // PTNODE(knopLabel , "label" ,None ,Label,fnopNone)
  348. case knopLabel:
  349. // TODO: print labeled statement
  350. break;
  351. // PTNODE(knopSwitch , "switch" ,None ,Switch,fnopBreak)
  352. case knopSwitch:
  353. Visit(pnode->sxSwitch.pnodeVal, byteCodeGenerator, prefix, postfix);
  354. BeginVisitBlock(pnode->sxSwitch.pnodeBlock, byteCodeGenerator);
  355. for (ParseNode *pnodeT = pnode->sxSwitch.pnodeCases; nullptr != pnodeT; pnodeT = pnodeT->sxCase.pnodeNext)
  356. {
  357. Visit(pnodeT, byteCodeGenerator, prefix, postfix, pnode);
  358. }
  359. Visit(pnode->sxSwitch.pnodeBlock, byteCodeGenerator, prefix, postfix);
  360. EndVisitBlock(pnode->sxSwitch.pnodeBlock, byteCodeGenerator);
  361. break;
  362. // PTNODE(knopCase , "case" ,None ,Case ,fnopNone)
  363. case knopCase:
  364. Visit(pnode->sxCase.pnodeExpr, byteCodeGenerator, prefix, postfix);
  365. Visit(pnode->sxCase.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  366. break;
  367. case knopTypeof:
  368. Visit(pnode->sxUni.pnode1, byteCodeGenerator, prefix, postfix);
  369. break;
  370. // PTNODE(knopTryCatchFinally,"try-catch-finally",None,TryCatchFinally,fnopCleanup)
  371. case knopTryFinally:
  372. Visit(pnode->sxTryFinally.pnodeTry, byteCodeGenerator, prefix, postfix, pnode);
  373. Visit(pnode->sxTryFinally.pnodeFinally, byteCodeGenerator, prefix, postfix, pnode);
  374. break;
  375. // PTNODE(knopTryCatch , "try-catch" ,None ,TryCatch ,fnopCleanup)
  376. case knopTryCatch:
  377. Visit(pnode->sxTryCatch.pnodeTry, byteCodeGenerator, prefix, postfix, pnode);
  378. Visit(pnode->sxTryCatch.pnodeCatch, byteCodeGenerator, prefix, postfix, pnode);
  379. break;
  380. // PTNODE(knopTry , "try" ,None ,Try ,fnopCleanup)
  381. case knopTry:
  382. Visit(pnode->sxTry.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  383. break;
  384. case knopCatch:
  385. BeginVisitCatch(pnode, byteCodeGenerator);
  386. Visit(pnode->sxCatch.pnodeParam, byteCodeGenerator, prefix, postfix);
  387. Visit(pnode->sxCatch.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  388. EndVisitCatch(pnode, byteCodeGenerator);
  389. break;
  390. case knopFinally:
  391. Visit(pnode->sxFinally.pnodeBody, byteCodeGenerator, prefix, postfix, pnode);
  392. break;
  393. // PTNODE(knopThrow , "throw" ,None ,Uni ,fnopNone)
  394. case knopThrow:
  395. Visit(pnode->sxUni.pnode1, byteCodeGenerator, prefix, postfix);
  396. break;
  397. case knopArray:
  398. {
  399. bool arrayLitOpt = EmitAsConstantArray(pnode, byteCodeGenerator);
  400. if (!arrayLitOpt)
  401. {
  402. Visit(pnode->sxUni.pnode1, byteCodeGenerator, prefix, postfix);
  403. }
  404. break;
  405. }
  406. case knopComma:
  407. {
  408. ParseNode *pnode1 = pnode->sxBin.pnode1;
  409. if (pnode1->nop == knopComma)
  410. {
  411. // Spot-fix to avoid recursion on very large comma expressions.
  412. ArenaAllocator *alloc = byteCodeGenerator->GetAllocator();
  413. SList<ParseNode*> rhsStack(alloc);
  414. do
  415. {
  416. rhsStack.Push(pnode1->sxBin.pnode2);
  417. pnode1 = pnode1->sxBin.pnode1;
  418. }
  419. while (pnode1->nop == knopComma);
  420. Visit(pnode1, byteCodeGenerator, prefix, postfix);
  421. while (!rhsStack.Empty())
  422. {
  423. ParseNode *pnodeRhs = rhsStack.Pop();
  424. Visit(pnodeRhs, byteCodeGenerator, prefix, postfix);
  425. }
  426. }
  427. else
  428. {
  429. Visit(pnode1, byteCodeGenerator, prefix, postfix);
  430. }
  431. Visit(pnode->sxBin.pnode2, byteCodeGenerator, prefix, postfix);
  432. }
  433. break;
  434. }
  435. if (pnodeParent)
  436. {
  437. PropagateFlags(pnode, pnodeParent);
  438. }
  439. postfix(pnode, byteCodeGenerator);
  440. }
  441. bool IsJump(ParseNode *pnode)
  442. {
  443. switch (pnode->nop)
  444. {
  445. case knopBreak:
  446. case knopContinue:
  447. case knopThrow:
  448. case knopReturn:
  449. return true;
  450. case knopBlock:
  451. case knopDoWhile:
  452. case knopWhile:
  453. case knopWith:
  454. case knopIf:
  455. case knopForIn:
  456. case knopForOf:
  457. case knopFor:
  458. case knopSwitch:
  459. case knopCase:
  460. case knopTryFinally:
  461. case knopTryCatch:
  462. case knopTry:
  463. case knopCatch:
  464. case knopFinally:
  465. return (pnode->sxStmt.grfnop & fnopJump) != 0;
  466. default:
  467. return false;
  468. }
  469. }
  470. void PropagateFlags(ParseNode *pnodeChild, ParseNode *pnodeParent)
  471. {
  472. if (IsJump(pnodeChild))
  473. {
  474. pnodeParent->sxStmt.grfnop |= fnopJump;
  475. }
  476. }
  477. void Bind(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator);
  478. void BindReference(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator);
  479. void AssignRegisters(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator);
  480. // TODO[ianhall]: This should be in a shared AST Utility header or source file
  481. bool IsExpressionStatement(ParseNode* stmt, const Js::ScriptContext *const scriptContext)
  482. {
  483. if (stmt->nop == knopFncDecl)
  484. {
  485. // 'knopFncDecl' is used for both function declarations and function expressions. In a program, a function expression
  486. // produces the function object that is created for the function expression as its value for the program. A function
  487. // declaration does not produce a value for the program.
  488. return !stmt->sxFnc.IsDeclaration();
  489. }
  490. if ((stmt->nop >= 0) && (stmt->nop<knopLim))
  491. {
  492. return (ParseNode::Grfnop(stmt->nop) & fnopNotExprStmt) == 0;
  493. }
  494. return false;
  495. }
  496. bool MustProduceValue(ParseNode *pnode, const Js::ScriptContext *const scriptContext)
  497. {
  498. // Determine whether the current statement is guaranteed to produce a value.
  499. if (IsExpressionStatement(pnode, scriptContext))
  500. {
  501. // These are trivially true.
  502. return true;
  503. }
  504. for (;;)
  505. {
  506. switch (pnode->nop)
  507. {
  508. case knopFor:
  509. // Check the common "for (;;)" case.
  510. if (pnode->sxFor.pnodeCond != nullptr ||
  511. pnode->sxFor.pnodeBody == nullptr)
  512. {
  513. return false;
  514. }
  515. // Loop body is always executed. Look at the loop body next.
  516. pnode = pnode->sxFor.pnodeBody;
  517. break;
  518. case knopIf:
  519. // True only if both "if" and "else" exist, and both produce values.
  520. if (pnode->sxIf.pnodeTrue == nullptr ||
  521. pnode->sxIf.pnodeFalse == nullptr)
  522. {
  523. return false;
  524. }
  525. if (!MustProduceValue(pnode->sxIf.pnodeFalse, scriptContext))
  526. {
  527. return false;
  528. }
  529. pnode = pnode->sxIf.pnodeTrue;
  530. break;
  531. case knopWhile:
  532. // Check the common "while (1)" case.
  533. if (pnode->sxWhile.pnodeBody == nullptr ||
  534. (pnode->sxWhile.pnodeCond &&
  535. (pnode->sxWhile.pnodeCond->nop != knopInt ||
  536. pnode->sxWhile.pnodeCond->sxInt.lw == 0)))
  537. {
  538. return false;
  539. }
  540. // Loop body is always executed. Look at the loop body next.
  541. pnode = pnode->sxWhile.pnodeBody;
  542. break;
  543. case knopDoWhile:
  544. if (pnode->sxWhile.pnodeBody == nullptr)
  545. {
  546. return false;
  547. }
  548. // Loop body is always executed. Look at the loop body next.
  549. pnode = pnode->sxWhile.pnodeBody;
  550. break;
  551. case knopBlock:
  552. return pnode->sxBlock.pnodeLastValStmt != nullptr;
  553. case knopWith:
  554. if (pnode->sxWith.pnodeBody == nullptr)
  555. {
  556. return false;
  557. }
  558. pnode = pnode->sxWith.pnodeBody;
  559. break;
  560. case knopSwitch:
  561. {
  562. // This is potentially the most inefficient case. We could consider adding a flag to the PnSwitch
  563. // struct and computing it when we visit the switch, but:
  564. // a. switch statements at global scope shouldn't be that common;
  565. // b. switch statements with many arms shouldn't be that common;
  566. // c. switches without default cases can be trivially skipped.
  567. if (pnode->sxSwitch.pnodeDefault == nullptr)
  568. {
  569. // Can't guarantee that any code is executed.
  570. return false;
  571. }
  572. ParseNode *pnodeCase;
  573. for (pnodeCase = pnode->sxSwitch.pnodeCases; pnodeCase; pnodeCase = pnodeCase->sxCase.pnodeNext)
  574. {
  575. if (pnodeCase->sxCase.pnodeBody == nullptr)
  576. {
  577. if (pnodeCase->sxCase.pnodeNext == nullptr)
  578. {
  579. // Last case has no code to execute.
  580. return false;
  581. }
  582. // Fall through to the next case.
  583. }
  584. else
  585. {
  586. if (!MustProduceValue(pnodeCase->sxCase.pnodeBody, scriptContext))
  587. {
  588. return false;
  589. }
  590. }
  591. }
  592. return true;
  593. }
  594. case knopTryCatch:
  595. // True only if both try and catch produce a value.
  596. if (pnode->sxTryCatch.pnodeTry->sxTry.pnodeBody == nullptr ||
  597. pnode->sxTryCatch.pnodeCatch->sxCatch.pnodeBody == nullptr)
  598. {
  599. return false;
  600. }
  601. if (!MustProduceValue(pnode->sxTryCatch.pnodeCatch->sxCatch.pnodeBody, scriptContext))
  602. {
  603. return false;
  604. }
  605. pnode = pnode->sxTryCatch.pnodeTry->sxTry.pnodeBody;
  606. break;
  607. case knopTryFinally:
  608. if (pnode->sxTryFinally.pnodeFinally->sxFinally.pnodeBody == nullptr)
  609. {
  610. // No finally body: look at the try body.
  611. if (pnode->sxTryFinally.pnodeTry->sxTry.pnodeBody == nullptr)
  612. {
  613. return false;
  614. }
  615. pnode = pnode->sxTryFinally.pnodeTry->sxTry.pnodeBody;
  616. break;
  617. }
  618. // Skip the try body, since the finally body will always follow it.
  619. pnode = pnode->sxTryFinally.pnodeFinally->sxFinally.pnodeBody;
  620. break;
  621. default:
  622. return false;
  623. }
  624. }
  625. }
  626. ByteCodeGenerator::ByteCodeGenerator(Js::ScriptContext* scriptContext, Js::ScopeInfo* parentScopeInfo) :
  627. alloc(nullptr),
  628. scriptContext(scriptContext),
  629. flags(0),
  630. funcInfoStack(nullptr),
  631. pRootFunc(nullptr),
  632. pCurrentFunction(nullptr),
  633. globalScope(nullptr),
  634. currentScope(nullptr),
  635. parentScopeInfo(parentScopeInfo),
  636. dynamicScopeCount(0),
  637. isBinding(false),
  638. propertyRecords(nullptr),
  639. inDestructuredPattern(false)
  640. {
  641. m_writer.Create();
  642. }
  643. /* static */
  644. bool ByteCodeGenerator::IsFalse(ParseNode* node)
  645. {
  646. return (node->nop == knopInt && node->sxInt.lw == 0) || node->nop == knopFalse;
  647. }
  648. bool ByteCodeGenerator::UseParserBindings() const
  649. {
  650. return IsInNonDebugMode() && !PHASE_OFF1(Js::ParserBindPhase);
  651. }
  652. bool ByteCodeGenerator::IsES6DestructuringEnabled() const
  653. {
  654. return scriptContext->GetConfig()->IsES6DestructuringEnabled();
  655. }
  656. bool ByteCodeGenerator::IsES6ForLoopSemanticsEnabled() const
  657. {
  658. return scriptContext->GetConfig()->IsES6ForLoopSemanticsEnabled();
  659. }
  660. // ByteCodeGenerator debug mode means we are generating debug mode user-code. Library code is always in non-debug mode.
  661. bool ByteCodeGenerator::IsInDebugMode() const
  662. {
  663. return scriptContext->IsInDebugMode() && !m_utf8SourceInfo->GetIsLibraryCode();
  664. }
  665. // ByteCodeGenerator non-debug mode means we are not debugging, or we are generating library code which is always in non-debug mode.
  666. bool ByteCodeGenerator::IsInNonDebugMode() const
  667. {
  668. return scriptContext->IsInNonDebugMode() || m_utf8SourceInfo->GetIsLibraryCode();
  669. }
  670. bool ByteCodeGenerator::ShouldTrackDebuggerMetadata() const
  671. {
  672. return (IsInDebugMode())
  673. #if DBG_DUMP
  674. || (Js::Configuration::Global.flags.Debug)
  675. #endif
  676. ;
  677. }
  678. void ByteCodeGenerator::SetRootFuncInfo(FuncInfo* func)
  679. {
  680. Assert(pRootFunc == nullptr || pRootFunc == func->byteCodeFunction || !IsInNonDebugMode());
  681. if (this->flags & (fscrImplicitThis | fscrImplicitParents))
  682. {
  683. // Mark a top-level event handler, since it will need to construct the "this" pointer's
  684. // namespace hierarchy to access globals.
  685. Assert(!func->IsGlobalFunction());
  686. func->SetIsEventHandler(true);
  687. }
  688. if (pRootFunc)
  689. {
  690. return;
  691. }
  692. this->pRootFunc = func->byteCodeFunction->GetParseableFunctionInfo();
  693. }
  694. Js::RegSlot ByteCodeGenerator::NextVarRegister()
  695. {
  696. return funcInfoStack->Top()->NextVarRegister();
  697. }
  698. Js::RegSlot ByteCodeGenerator::NextConstRegister()
  699. {
  700. return funcInfoStack->Top()->NextConstRegister();
  701. }
  702. FuncInfo * ByteCodeGenerator::TopFuncInfo() const
  703. {
  704. return funcInfoStack->Empty() ? nullptr : funcInfoStack->Top();
  705. }
  706. void ByteCodeGenerator::EnterLoop()
  707. {
  708. if (this->TopFuncInfo())
  709. {
  710. this->TopFuncInfo()->hasLoop = true;
  711. }
  712. loopDepth++;
  713. }
  714. void ByteCodeGenerator::SetHasTry(bool has)
  715. {
  716. TopFuncInfo()->GetParsedFunctionBody()->SetHasTry(has);
  717. }
  718. void ByteCodeGenerator::SetHasFinally(bool has)
  719. {
  720. TopFuncInfo()->GetParsedFunctionBody()->SetHasFinally(has);
  721. }
  722. // TODO: per-function register assignment for env and global symbols
  723. void ByteCodeGenerator::AssignRegister(Symbol *sym)
  724. {
  725. AssertMsg(sym->GetDecl() == nullptr || sym->GetDecl()->nop != knopConstDecl || sym->GetDecl()->nop != knopLetDecl,
  726. "const and let should get only temporary register, assigned during emit stage");
  727. if (sym->GetLocation() == Js::Constants::NoRegister)
  728. {
  729. sym->SetLocation(NextVarRegister());
  730. }
  731. }
  732. void ByteCodeGenerator::AddTargetStmt(ParseNode *pnodeStmt)
  733. {
  734. FuncInfo *top = funcInfoStack->Top();
  735. top->AddTargetStmt(pnodeStmt);
  736. }
  737. Js::RegSlot ByteCodeGenerator::AssignNullConstRegister()
  738. {
  739. FuncInfo *top = funcInfoStack->Top();
  740. return top->AssignNullConstRegister();
  741. }
  742. Js::RegSlot ByteCodeGenerator::AssignUndefinedConstRegister()
  743. {
  744. FuncInfo *top = funcInfoStack->Top();
  745. return top->AssignUndefinedConstRegister();
  746. }
  747. Js::RegSlot ByteCodeGenerator::AssignTrueConstRegister()
  748. {
  749. FuncInfo *top = funcInfoStack->Top();
  750. return top->AssignTrueConstRegister();
  751. }
  752. Js::RegSlot ByteCodeGenerator::AssignFalseConstRegister()
  753. {
  754. FuncInfo *top = funcInfoStack->Top();
  755. return top->AssignFalseConstRegister();
  756. }
  757. Js::RegSlot ByteCodeGenerator::AssignThisRegister()
  758. {
  759. FuncInfo *top = funcInfoStack->Top();
  760. return top->AssignThisRegister();
  761. }
  762. Js::RegSlot ByteCodeGenerator::AssignNewTargetRegister()
  763. {
  764. FuncInfo *top = funcInfoStack->Top();
  765. return top->AssignNewTargetRegister();
  766. }
  767. void ByteCodeGenerator::SetNeedEnvRegister()
  768. {
  769. FuncInfo *top = funcInfoStack->Top();
  770. top->SetNeedEnvRegister();
  771. }
  772. void ByteCodeGenerator::AssignFrameObjRegister()
  773. {
  774. FuncInfo* top = funcInfoStack->Top();
  775. if (top->frameObjRegister == Js::Constants::NoRegister)
  776. {
  777. top->frameObjRegister = top->NextVarRegister();
  778. }
  779. }
  780. void ByteCodeGenerator::AssignFrameDisplayRegister()
  781. {
  782. FuncInfo* top = funcInfoStack->Top();
  783. if (top->frameDisplayRegister == Js::Constants::NoRegister)
  784. {
  785. top->frameDisplayRegister = top->NextVarRegister();
  786. }
  787. }
  788. void ByteCodeGenerator::AssignFrameSlotsRegister()
  789. {
  790. FuncInfo* top = funcInfoStack->Top();
  791. if (top->frameSlotsRegister == Js::Constants::NoRegister)
  792. {
  793. top->frameSlotsRegister = NextVarRegister();
  794. }
  795. }
  796. void ByteCodeGenerator::SetNumberOfInArgs(Js::ArgSlot argCount)
  797. {
  798. FuncInfo *top = funcInfoStack->Top();
  799. top->inArgsCount = argCount;
  800. }
  801. Js::RegSlot ByteCodeGenerator::EnregisterConstant(unsigned int constant)
  802. {
  803. Js::RegSlot loc = Js::Constants::NoRegister;
  804. FuncInfo *top = funcInfoStack->Top();
  805. if (!top->constantToRegister.TryGetValue(constant, &loc))
  806. {
  807. loc = NextConstRegister();
  808. top->constantToRegister.Add(constant, loc);
  809. }
  810. return loc;
  811. }
  812. Js::RegSlot ByteCodeGenerator::EnregisterStringConstant(IdentPtr pid)
  813. {
  814. Js::RegSlot loc = Js::Constants::NoRegister;
  815. FuncInfo *top = funcInfoStack->Top();
  816. if (!top->stringToRegister.TryGetValue(pid, &loc))
  817. {
  818. loc = NextConstRegister();
  819. top->stringToRegister.Add(pid, loc);
  820. }
  821. return loc;
  822. }
  823. Js::RegSlot ByteCodeGenerator::EnregisterDoubleConstant(double d)
  824. {
  825. Js::RegSlot loc = Js::Constants::NoRegister;
  826. FuncInfo *top = funcInfoStack->Top();
  827. if (!top->TryGetDoubleLoc(d, &loc))
  828. {
  829. loc = NextConstRegister();
  830. top->AddDoubleConstant(d, loc);
  831. }
  832. return loc;
  833. }
  834. Js::RegSlot ByteCodeGenerator::EnregisterStringTemplateCallsiteConstant(ParseNode* pnode)
  835. {
  836. Assert(pnode->nop == knopStrTemplate);
  837. Assert(pnode->sxStrTemplate.isTaggedTemplate);
  838. Js::RegSlot loc = Js::Constants::NoRegister;
  839. FuncInfo* top = funcInfoStack->Top();
  840. if (!top->stringTemplateCallsiteRegisterMap.TryGetValue(pnode, &loc))
  841. {
  842. loc = NextConstRegister();
  843. top->stringTemplateCallsiteRegisterMap.Add(pnode, loc);
  844. }
  845. return loc;
  846. }
  847. //
  848. // Restore all outer func scope info when reparsing a deferred func.
  849. //
  850. void ByteCodeGenerator::RestoreScopeInfo(Js::FunctionBody* functionBody)
  851. {
  852. if (functionBody && functionBody->GetScopeInfo())
  853. {
  854. PROBE_STACK(scriptContext, Js::Constants::MinStackByteCodeVisitor);
  855. Js::ScopeInfo* scopeInfo = functionBody->GetScopeInfo();
  856. RestoreScopeInfo(scopeInfo->GetParent()); // Recursively restore outer func scope info
  857. Js::ScopeInfo* paramScopeInfo = scopeInfo->GetParamScopeInfo();
  858. Scope* paramScope = nullptr;
  859. if (paramScopeInfo != nullptr)
  860. {
  861. paramScope = paramScopeInfo->GetScope();
  862. Assert(paramScope || !UseParserBindings());
  863. if (paramScope == nullptr || !UseParserBindings())
  864. {
  865. paramScope = Anew(alloc, Scope, alloc, ScopeType_Parameter, true);
  866. }
  867. // We need the funcInfo before continuing the restoration of the param scope, so wait for the funcInfo to be created.
  868. }
  869. Scope* bodyScope = scopeInfo->GetScope();
  870. Assert(bodyScope || !UseParserBindings());
  871. if (bodyScope == nullptr || !UseParserBindings())
  872. {
  873. if (scopeInfo->IsGlobalEval())
  874. {
  875. bodyScope = Anew(alloc, Scope, alloc, ScopeType_GlobalEvalBlock, true);
  876. }
  877. else
  878. {
  879. bodyScope = Anew(alloc, Scope, alloc, ScopeType_FunctionBody, true);
  880. }
  881. }
  882. FuncInfo* func = Anew(alloc, FuncInfo, functionBody->GetDisplayName(), alloc, paramScope, bodyScope, nullptr, functionBody);
  883. if (paramScope != nullptr)
  884. {
  885. paramScope->SetFunc(func);
  886. paramScopeInfo->GetScopeInfo(nullptr, this, func, paramScope);
  887. }
  888. if (bodyScope->GetScopeType() == ScopeType_GlobalEvalBlock)
  889. {
  890. func->bodyScope = this->currentScope;
  891. }
  892. PushFuncInfo(L"RestoreScopeInfo", func);
  893. if (!functionBody->DoStackNestedFunc())
  894. {
  895. func->hasEscapedUseNestedFunc = true;
  896. }
  897. Js::ScopeInfo* funcExprScopeInfo = scopeInfo->GetFuncExprScopeInfo();
  898. if (funcExprScopeInfo)
  899. {
  900. Scope* funcExprScope = funcExprScopeInfo->GetScope();
  901. Assert(funcExprScope || !UseParserBindings());
  902. if (funcExprScope == nullptr || !UseParserBindings())
  903. {
  904. funcExprScope = Anew(alloc, Scope, alloc, ScopeType_FuncExpr, true);
  905. }
  906. funcExprScope->SetFunc(func);
  907. func->SetFuncExprScope(funcExprScope);
  908. funcExprScopeInfo->GetScopeInfo(nullptr, this, func, funcExprScope);
  909. }
  910. scopeInfo->GetScopeInfo(nullptr, this, func, bodyScope);
  911. }
  912. else
  913. {
  914. Assert(this->TopFuncInfo() == nullptr);
  915. // funcBody is glo
  916. currentScope = Anew(alloc, Scope, alloc, ScopeType_Global, !UseParserBindings());
  917. globalScope = currentScope;
  918. FuncInfo *func = Anew(alloc, FuncInfo, Js::Constants::GlobalFunction,
  919. alloc, nullptr, currentScope, nullptr, functionBody);
  920. PushFuncInfo(L"RestoreScopeInfo", func);
  921. }
  922. }
  923. FuncInfo * ByteCodeGenerator::StartBindGlobalStatements(ParseNode *pnode)
  924. {
  925. if (parentScopeInfo)
  926. {
  927. Assert(CONFIG_FLAG(DeferNested));
  928. trackEnvDepth = true;
  929. RestoreScopeInfo(parentScopeInfo->GetParent());
  930. trackEnvDepth = false;
  931. // "currentScope" is the parentFunc scope. This ensures the deferred func declaration
  932. // symbol will bind to the func declaration symbol already available in parentFunc scope.
  933. }
  934. else
  935. {
  936. currentScope = pnode->sxProg.scope;
  937. Assert(currentScope);
  938. if (!currentScope || !UseParserBindings())
  939. {
  940. currentScope = Anew(alloc, Scope, alloc, ScopeType_Global, true);
  941. pnode->sxProg.scope = currentScope;
  942. }
  943. globalScope = currentScope;
  944. }
  945. Js::FunctionBody * byteCodeFunction;
  946. if (!IsInNonDebugMode() && this->pCurrentFunction != nullptr && this->pCurrentFunction->GetIsGlobalFunc() && !this->pCurrentFunction->IsFakeGlobalFunc(flags))
  947. {
  948. // we will re-use the global FunctionBody which was created before deferred parse.
  949. byteCodeFunction = this->pCurrentFunction;
  950. byteCodeFunction->RemoveDeferParseAttribute();
  951. byteCodeFunction->ResetByteCodeGenVisitState();
  952. if (byteCodeFunction->GetBoundPropertyRecords() == nullptr)
  953. {
  954. Assert(!IsInNonDebugMode());
  955. // This happens when we try to re-use the function body which was created due to serialized bytecode.
  956. byteCodeFunction->SetBoundPropertyRecords(EnsurePropertyRecordList());
  957. }
  958. }
  959. else if ((this->flags & fscrDeferredFnc))
  960. {
  961. byteCodeFunction = this->EnsureFakeGlobalFuncForUndefer(pnode);
  962. }
  963. else
  964. {
  965. byteCodeFunction = this->MakeGlobalFunctionBody(pnode);
  966. // Mark this global function to required for register script event
  967. byteCodeFunction->SetIsTopLevel(true);
  968. if (pnode->sxFnc.GetStrictMode() != 0)
  969. {
  970. byteCodeFunction->SetIsStrictMode();
  971. }
  972. }
  973. if (byteCodeFunction->IsReparsed())
  974. {
  975. byteCodeFunction->RestoreState(pnode);
  976. }
  977. else
  978. {
  979. byteCodeFunction->SaveState(pnode);
  980. }
  981. FuncInfo *funcInfo = Anew(alloc, FuncInfo, Js::Constants::GlobalFunction,
  982. alloc, nullptr, globalScope, pnode, byteCodeFunction);
  983. long currentAstSize = pnode->sxFnc.astSize;
  984. if (currentAstSize > this->maxAstSize)
  985. {
  986. this->maxAstSize = currentAstSize;
  987. }
  988. PushFuncInfo(L"StartBindGlobalStatements", funcInfo);
  989. return funcInfo;
  990. }
  991. void ByteCodeGenerator::AssignPropertyId(IdentPtr pid)
  992. {
  993. if (pid->GetPropertyId() == Js::Constants::NoProperty)
  994. {
  995. Js::PropertyId id = TopFuncInfo()->byteCodeFunction->GetOrAddPropertyIdTracked(SymbolName(pid->Psz(), pid->Cch()));
  996. pid->SetPropertyId(id);
  997. }
  998. }
  999. void ByteCodeGenerator::AssignPropertyId(Symbol *sym, Js::ParseableFunctionInfo* functionInfo)
  1000. {
  1001. sym->SetPosition(functionInfo->GetOrAddPropertyIdTracked(sym->GetName()));
  1002. }
  1003. template <class PrefixFn, class PostfixFn>
  1004. ParseNode* VisitBlock(ParseNode *pnode, ByteCodeGenerator* byteCodeGenerator, PrefixFn prefix, PostfixFn postfix, ParseNode *pnodeParent = nullptr)
  1005. {
  1006. ParseNode *pnodeLastVal = nullptr;
  1007. if (pnode != nullptr)
  1008. {
  1009. bool fTrackVal = byteCodeGenerator->IsBinding() &&
  1010. (byteCodeGenerator->GetFlags() & fscrReturnExpression) &&
  1011. byteCodeGenerator->TopFuncInfo()->IsGlobalFunction();
  1012. while (pnode->nop == knopList)
  1013. {
  1014. Visit(pnode->sxBin.pnode1, byteCodeGenerator, prefix, postfix, pnodeParent);
  1015. if (fTrackVal)
  1016. {
  1017. // If we're tracking values, find the last statement (if any) in the block that is
  1018. // guaranteed to produce a value.
  1019. if (MustProduceValue(pnode->sxBin.pnode1, byteCodeGenerator->GetScriptContext()))
  1020. {
  1021. pnodeLastVal = pnode->sxBin.pnode1;
  1022. }
  1023. if (IsJump(pnode->sxBin.pnode1))
  1024. {
  1025. // This is a jump out of the current block. The remaining instructions (if any)
  1026. // will not be executed, so stop tracking them.
  1027. fTrackVal = false;
  1028. }
  1029. }
  1030. pnode = pnode->sxBin.pnode2;
  1031. }
  1032. Visit(pnode, byteCodeGenerator, prefix, postfix, pnodeParent);
  1033. if (fTrackVal)
  1034. {
  1035. if (MustProduceValue(pnode, byteCodeGenerator->GetScriptContext()))
  1036. {
  1037. pnodeLastVal = pnode;
  1038. }
  1039. }
  1040. }
  1041. return pnodeLastVal;
  1042. }
  1043. FuncInfo * ByteCodeGenerator::StartBindFunction(const wchar_t *name, uint nameLength, uint shortNameOffset, bool* pfuncExprWithName, ParseNode *pnode)
  1044. {
  1045. bool funcExprWithName;
  1046. union
  1047. {
  1048. Js::ParseableFunctionInfo* parseableFunctionInfo;
  1049. Js::FunctionBody* parsedFunctionBody;
  1050. };
  1051. bool isDeferParsed = false;
  1052. if (this->pCurrentFunction &&
  1053. this->pCurrentFunction->IsFunctionParsed())
  1054. {
  1055. Assert(this->pCurrentFunction->StartInDocument() == pnode->ichMin);
  1056. Assert(this->pCurrentFunction->LengthInChars() == pnode->LengthInCodepoints());
  1057. // This is the root function for the current AST subtree, and it already has a FunctionBody
  1058. // (created by a deferred parse) which we're now filling in.
  1059. parsedFunctionBody = this->pCurrentFunction;
  1060. parsedFunctionBody->RemoveDeferParseAttribute();
  1061. if (parsedFunctionBody->GetBoundPropertyRecords() == nullptr)
  1062. {
  1063. // This happens when we try to re-use the function body which was created due to serialized bytecode.
  1064. parsedFunctionBody->SetBoundPropertyRecords(EnsurePropertyRecordList());
  1065. }
  1066. Assert(!parsedFunctionBody->IsDeferredParseFunction() || parsedFunctionBody->IsReparsed());
  1067. pnode->sxFnc.SetDeclaration(parsedFunctionBody->GetIsDeclaration());
  1068. funcExprWithName =
  1069. !(parsedFunctionBody->GetIsDeclaration() || pnode->sxFnc.IsMethod()) &&
  1070. pnode->sxFnc.pnodeName != nullptr &&
  1071. pnode->sxFnc.pnodeName->nop == knopVarDecl;
  1072. *pfuncExprWithName = funcExprWithName;
  1073. Assert(parsedFunctionBody->GetLocalFunctionId() == pnode->sxFnc.functionId || !IsInNonDebugMode());
  1074. // Some state may be tracked on the function body during the visit pass. Since the previous visit pass may have failed,
  1075. // we need to reset the state on the function body.
  1076. parsedFunctionBody->ResetByteCodeGenVisitState();
  1077. if (parsedFunctionBody->GetScopeInfo())
  1078. {
  1079. // Propagate flags from the (real) parent function.
  1080. Js::ParseableFunctionInfo *parent = parsedFunctionBody->GetScopeInfo()->GetParent();
  1081. if (parent)
  1082. {
  1083. Assert(parent->GetFunctionBody());
  1084. if (parent->GetFunctionBody()->GetHasOrParentHasArguments())
  1085. {
  1086. parsedFunctionBody->SetHasOrParentHasArguments(true);
  1087. }
  1088. }
  1089. }
  1090. }
  1091. else
  1092. {
  1093. funcExprWithName = *pfuncExprWithName;
  1094. Js::LocalFunctionId functionId = pnode->sxFnc.functionId;
  1095. isDeferParsed = (pnode->sxFnc.pnodeBody == nullptr);
  1096. // Create a function body if:
  1097. // 1. The parse node is not defer parsed
  1098. // 2. Or creating function proxies is disallowed
  1099. bool createFunctionBody = !isDeferParsed;
  1100. if (!CONFIG_FLAG(CreateFunctionProxy)) createFunctionBody = true;
  1101. Js::FunctionInfo::Attributes attributes = Js::FunctionInfo::Attributes::None;
  1102. if (pnode->sxFnc.IsAsync())
  1103. {
  1104. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::ErrorOnNew | Js::FunctionInfo::Attributes::Async);
  1105. }
  1106. if (pnode->sxFnc.IsLambda())
  1107. {
  1108. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::ErrorOnNew | Js::FunctionInfo::Attributes::Lambda);
  1109. }
  1110. if (pnode->sxFnc.HasSuperReference())
  1111. {
  1112. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::SuperReference);
  1113. }
  1114. if (pnode->sxFnc.IsClassMember())
  1115. {
  1116. if (pnode->sxFnc.IsClassConstructor())
  1117. {
  1118. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::ClassConstructor);
  1119. }
  1120. else
  1121. {
  1122. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::ErrorOnNew | Js::FunctionInfo::Attributes::ClassMethod);
  1123. }
  1124. }
  1125. if (pnode->sxFnc.IsGenerator())
  1126. {
  1127. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::Generator);
  1128. }
  1129. if (pnode->sxFnc.IsAccessor())
  1130. {
  1131. attributes = (Js::FunctionInfo::Attributes)(attributes | Js::FunctionInfo::Attributes::ErrorOnNew);
  1132. }
  1133. if (createFunctionBody)
  1134. {
  1135. ENTER_PINNED_SCOPE(Js::PropertyRecordList, propertyRecordList);
  1136. propertyRecordList = EnsurePropertyRecordList();
  1137. parsedFunctionBody = Js::FunctionBody::NewFromRecycler(scriptContext, name, nameLength, shortNameOffset, pnode->sxFnc.nestedCount, m_utf8SourceInfo,
  1138. m_utf8SourceInfo->GetSrcInfo()->sourceContextInfo->sourceContextId, functionId, propertyRecordList
  1139. , attributes
  1140. #ifdef PERF_COUNTERS
  1141. , false /* is function from deferred deserialized proxy */
  1142. #endif
  1143. );
  1144. LEAVE_PINNED_SCOPE();
  1145. }
  1146. else
  1147. {
  1148. ENTER_PINNED_SCOPE(Js::PropertyRecordList, propertyRecordList);
  1149. propertyRecordList = nullptr;
  1150. if (funcExprWithName)
  1151. {
  1152. propertyRecordList = EnsurePropertyRecordList();
  1153. }
  1154. parseableFunctionInfo = Js::ParseableFunctionInfo::New(scriptContext, pnode->sxFnc.nestedCount, functionId, m_utf8SourceInfo, name, nameLength, shortNameOffset, propertyRecordList, attributes);
  1155. LEAVE_PINNED_SCOPE();
  1156. }
  1157. // In either case register the function reference
  1158. scriptContext->RegisterDynamicFunctionReference(parseableFunctionInfo);
  1159. #if DBG
  1160. parseableFunctionInfo->deferredParseNextFunctionId = pnode->sxFnc.deferredParseNextFunctionId;
  1161. #endif
  1162. parseableFunctionInfo->SetIsDeclaration(pnode->sxFnc.IsDeclaration() != 0);
  1163. parseableFunctionInfo->SetIsAccessor(pnode->sxFnc.IsAccessor() != 0);
  1164. if (pnode->sxFnc.IsAccessor())
  1165. {
  1166. scriptContext->optimizationOverrides.SetSideEffects(Js::SideEffects_Accessor);
  1167. }
  1168. }
  1169. Scope *funcExprScope = nullptr;
  1170. if (funcExprWithName)
  1171. {
  1172. if (!UseParserBindings())
  1173. {
  1174. funcExprScope = Anew(alloc, Scope, alloc, ScopeType_FuncExpr, true);
  1175. pnode->sxFnc.scope = funcExprScope;
  1176. }
  1177. else
  1178. {
  1179. funcExprScope = pnode->sxFnc.scope;
  1180. Assert(funcExprScope);
  1181. }
  1182. PushScope(funcExprScope);
  1183. Symbol *sym = AddSymbolToScope(funcExprScope, name, nameLength, pnode->sxFnc.pnodeName, STFunction);
  1184. sym->SetFuncExpr(true);
  1185. sym->SetPosition(parsedFunctionBody->GetOrAddPropertyIdTracked(sym->GetName()));
  1186. pnode->sxFnc.SetFuncSymbol(sym);
  1187. }
  1188. Scope *paramScope = pnode->sxFnc.pnodeScopes ? pnode->sxFnc.pnodeScopes->sxBlock.scope : nullptr;
  1189. Scope *bodyScope = pnode->sxFnc.pnodeBodyScope ? pnode->sxFnc.pnodeBodyScope->sxBlock.scope : nullptr;
  1190. Assert(paramScope != nullptr || !pnode->sxFnc.pnodeScopes || !UseParserBindings());
  1191. if (paramScope == nullptr || !UseParserBindings())
  1192. {
  1193. paramScope = Anew(alloc, Scope, alloc, ScopeType_Parameter, true);
  1194. if (pnode->sxFnc.pnodeScopes)
  1195. {
  1196. pnode->sxFnc.pnodeScopes->sxBlock.scope = paramScope;
  1197. }
  1198. }
  1199. if (bodyScope == nullptr || !UseParserBindings())
  1200. {
  1201. bodyScope = Anew(alloc, Scope, alloc, ScopeType_FunctionBody, true);
  1202. if (pnode->sxFnc.pnodeBodyScope)
  1203. {
  1204. pnode->sxFnc.pnodeBodyScope->sxBlock.scope = bodyScope;
  1205. }
  1206. }
  1207. AssertMsg(pnode->nop == knopFncDecl, "Non-function declaration trying to create function body");
  1208. parseableFunctionInfo->SetIsGlobalFunc(false);
  1209. if (pnode->sxFnc.GetStrictMode() != 0)
  1210. {
  1211. parseableFunctionInfo->SetIsStrictMode();
  1212. }
  1213. FuncInfo *funcInfo = Anew(alloc, FuncInfo, name, alloc, paramScope, bodyScope, pnode, parseableFunctionInfo);
  1214. if (pnode->sxFnc.GetArgumentsObjectEscapes())
  1215. {
  1216. // If the parser detected that the arguments object escapes, then the function scope escapes
  1217. // and cannot be cached.
  1218. this->FuncEscapes(bodyScope);
  1219. funcInfo->SetHasMaybeEscapedNestedFunc(DebugOnly(L"ArgumentsObjectEscapes"));
  1220. }
  1221. if (!isDeferParsed)
  1222. {
  1223. if (parsedFunctionBody->IsReparsed())
  1224. {
  1225. parsedFunctionBody->RestoreState(pnode);
  1226. }
  1227. else
  1228. {
  1229. parsedFunctionBody->SaveState(pnode);
  1230. }
  1231. }
  1232. funcInfo->SetChildCallsEval(!!pnode->sxFnc.ChildCallsEval());
  1233. if (pnode->sxFnc.CallsEval())
  1234. {
  1235. funcInfo->SetCallsEval(true);
  1236. bodyScope->SetIsDynamic(true);
  1237. bodyScope->SetIsObject();
  1238. bodyScope->SetCapturesAll(true);
  1239. bodyScope->SetMustInstantiate(true);
  1240. paramScope->SetIsObject();
  1241. paramScope->SetMustInstantiate(true);
  1242. paramScope->SetCapturesAll(true);
  1243. }
  1244. PushFuncInfo(L"StartBindFunction", funcInfo);
  1245. PushScope(paramScope);
  1246. PushScope(bodyScope);
  1247. if (funcExprScope)
  1248. {
  1249. funcExprScope->SetFunc(funcInfo);
  1250. funcInfo->funcExprScope = funcExprScope;
  1251. }
  1252. long currentAstSize = pnode->sxFnc.astSize;
  1253. if (currentAstSize > this->maxAstSize)
  1254. {
  1255. this->maxAstSize = currentAstSize;
  1256. }
  1257. return funcInfo;
  1258. }
  1259. void ByteCodeGenerator::EndBindFunction(bool funcExprWithName)
  1260. {
  1261. bool isGlobalScope = currentScope->GetScopeType() == ScopeType_Global;
  1262. Assert(currentScope->GetScopeType() == ScopeType_FunctionBody || isGlobalScope);
  1263. PopScope(); // function body
  1264. if (isGlobalScope)
  1265. {
  1266. Assert(currentScope == nullptr);
  1267. }
  1268. else
  1269. {
  1270. Assert(currentScope->GetScopeType() == ScopeType_Parameter);
  1271. PopScope(); // parameter scope
  1272. }
  1273. if (funcExprWithName)
  1274. {
  1275. Assert(currentScope->GetScopeType() == ScopeType_FuncExpr);
  1276. PopScope();
  1277. }
  1278. funcInfoStack->Pop();
  1279. }
  1280. void ByteCodeGenerator::StartBindCatch(ParseNode *pnode)
  1281. {
  1282. Scope *scope = pnode->sxCatch.scope;
  1283. Assert(scope);
  1284. if (scope == nullptr || !UseParserBindings())
  1285. {
  1286. scope = Anew(alloc, Scope, alloc, (pnode->sxCatch.pnodeParam->nop == knopParamPattern) ? ScopeType_CatchParamPattern : ScopeType_Catch, true);
  1287. pnode->sxCatch.scope = scope;
  1288. }
  1289. Assert(currentScope);
  1290. scope->SetFunc(currentScope->GetFunc());
  1291. PushScope(scope);
  1292. }
  1293. void ByteCodeGenerator::EndBindCatch()
  1294. {
  1295. PopScope();
  1296. }
  1297. void ByteCodeGenerator::PushScope(Scope *innerScope)
  1298. {
  1299. Assert(innerScope != nullptr);
  1300. if (isBinding
  1301. && currentScope != nullptr
  1302. && currentScope->GetScopeType() == ScopeType_FunctionBody
  1303. && innerScope->GetMustInstantiate())
  1304. {
  1305. // If the current scope is a function body, we don't expect another function body
  1306. // without going through a function expression or parameter scope first. This may
  1307. // not be the case in the emit phase, where we can merge the two scopes. This also
  1308. // does not apply to incoming scopes marked as !mustInstantiate.
  1309. Assert(innerScope->GetScopeType() != ScopeType_FunctionBody);
  1310. }
  1311. innerScope->SetEnclosingScope(currentScope);
  1312. currentScope = innerScope;
  1313. if (currentScope->GetIsDynamic())
  1314. {
  1315. this->dynamicScopeCount++;
  1316. }
  1317. if (this->trackEnvDepth && currentScope->GetMustInstantiate())
  1318. {
  1319. this->envDepth++;
  1320. if (this->envDepth == 0)
  1321. {
  1322. Js::Throw::OutOfMemory();
  1323. }
  1324. }
  1325. }
  1326. void ByteCodeGenerator::PopScope()
  1327. {
  1328. Assert(currentScope != nullptr);
  1329. if (this->trackEnvDepth && currentScope->GetMustInstantiate())
  1330. {
  1331. this->envDepth--;
  1332. Assert(this->envDepth != (uint16)-1);
  1333. }
  1334. if (currentScope->GetIsDynamic())
  1335. {
  1336. this->dynamicScopeCount--;
  1337. }
  1338. currentScope = currentScope->GetEnclosingScope();
  1339. }
  1340. void ByteCodeGenerator::PushBlock(ParseNode *pnode)
  1341. {
  1342. pnode->sxBlock.SetEnclosingBlock(currentBlock);
  1343. currentBlock = pnode;
  1344. }
  1345. void ByteCodeGenerator::PopBlock()
  1346. {
  1347. currentBlock = currentBlock->sxBlock.GetEnclosingBlock();
  1348. }
  1349. void ByteCodeGenerator::PushFuncInfo(wchar_t const * location, FuncInfo* funcInfo)
  1350. {
  1351. // We might have multiple global scope for deferparse.
  1352. // Assert(!funcInfo->IsGlobalFunction() || this->TopFuncInfo() == nullptr || this->TopFuncInfo()->IsGlobalFunction());
  1353. if (PHASE_TRACE1(Js::ByteCodePhase))
  1354. {
  1355. Output::Print(L"%s: PushFuncInfo: %s", location, funcInfo->name);
  1356. if (this->TopFuncInfo())
  1357. {
  1358. Output::Print(L" Top: %s", this->TopFuncInfo()->name);
  1359. }
  1360. Output::Print(L"\n");
  1361. Output::Flush();
  1362. }
  1363. funcInfoStack->Push(funcInfo);
  1364. }
  1365. void ByteCodeGenerator::PopFuncInfo(wchar_t const * location)
  1366. {
  1367. FuncInfo * funcInfo = funcInfoStack->Pop();
  1368. // Assert(!funcInfo->IsGlobalFunction() || this->TopFuncInfo() == nullptr || this->TopFuncInfo()->IsGlobalFunction());
  1369. if (PHASE_TRACE1(Js::ByteCodePhase))
  1370. {
  1371. Output::Print(L"%s: PopFuncInfo: %s", location, funcInfo->name);
  1372. if (this->TopFuncInfo())
  1373. {
  1374. Output::Print(L" Top: %s", this->TopFuncInfo()->name);
  1375. }
  1376. Output::Print(L"\n");
  1377. Output::Flush();
  1378. }
  1379. }
  1380. Symbol * ByteCodeGenerator::FindSymbol(Symbol **symRef, IdentPtr pid, bool forReference)
  1381. {
  1382. const wchar_t *key = nullptr;
  1383. int keyLength;
  1384. Symbol *sym = nullptr;
  1385. if (!UseParserBindings())
  1386. {
  1387. key = reinterpret_cast<const wchar_t*>(pid->Psz());
  1388. keyLength = pid->Cch();
  1389. sym = currentScope->FindSymbol(SymbolName(key, keyLength), STUnknown);
  1390. if (symRef)
  1391. {
  1392. *symRef = sym;
  1393. }
  1394. }
  1395. else
  1396. {
  1397. Assert(symRef);
  1398. if (*symRef)
  1399. {
  1400. sym = *symRef;
  1401. }
  1402. else
  1403. {
  1404. this->AssignPropertyId(pid);
  1405. return nullptr;
  1406. }
  1407. key = reinterpret_cast<const wchar_t*>(sym->GetPid()->Psz());
  1408. }
  1409. Scope *symScope = sym->GetScope();
  1410. Assert(symScope);
  1411. #if DBG_DUMP
  1412. if (this->Trace())
  1413. {
  1414. if (sym != nullptr)
  1415. {
  1416. Output::Print(L"resolved %s to symbol of type %s: \n", key, sym->GetSymbolTypeName());
  1417. }
  1418. else
  1419. {
  1420. Output::Print(L"did not resolve %s\n", key);
  1421. }
  1422. }
  1423. #endif
  1424. if (!(sym->GetIsGlobal()))
  1425. {
  1426. FuncInfo *top = funcInfoStack->Top();
  1427. bool nonLocalRef = symScope->GetFunc() != top;
  1428. if (forReference)
  1429. {
  1430. Js::PropertyId i;
  1431. Scope *scope = FindScopeForSym(symScope, nullptr, &i, top);
  1432. // If we have a reference to a local within a with, we want to generate a closure represented by an object.
  1433. if (scope != symScope && scope->GetIsDynamic())
  1434. {
  1435. nonLocalRef = true;
  1436. symScope->SetIsObject();
  1437. }
  1438. }
  1439. if (nonLocalRef)
  1440. {
  1441. // Symbol referenced through a closure. Mark it as such and give it a property ID.
  1442. sym->SetHasNonLocalReference(true, this);
  1443. sym->SetPosition(top->byteCodeFunction->GetOrAddPropertyIdTracked(sym->GetName()));
  1444. // If this is var is local to a function (meaning that it belongs to the function's scope
  1445. // *or* to scope that need not be instantiated, like a function expression scope, which we'll
  1446. // merge with the function scope, then indicate that fact.
  1447. symScope->SetHasLocalInClosure(true);
  1448. if (symScope->GetFunc()->GetHasArguments() && sym->GetIsFormal())
  1449. {
  1450. // A formal is referenced non-locally. We need to allocate it on the heap, so
  1451. // do the same for the whole arguments object.
  1452. // Formal is referenced. So count of formals to function > 0.
  1453. // So no need to check for inParams here.
  1454. symScope->GetFunc()->SetHasHeapArguments(true);
  1455. }
  1456. if (symScope->GetFunc() != top)
  1457. {
  1458. top->SetHasClosureReference(true);
  1459. }
  1460. }
  1461. else if (sym->GetHasNonLocalReference() && !sym->GetIsCommittedToSlot() && !sym->HasVisitedCapturingFunc())
  1462. {
  1463. sym->SetHasNonCommittedReference(true);
  1464. }
  1465. if (sym->GetFuncExpr())
  1466. {
  1467. symScope->GetFunc()->SetFuncExprNameReference(true);
  1468. // If the func expr is captured by a closure, and if it's not getting its own scope,
  1469. // we have to make the function's scope a dynamic object. That's because we have to init
  1470. // the property as non-writable, and if we put it directly in the slots we can't protect it from being
  1471. // overwritten.
  1472. if (nonLocalRef && !symScope->GetFunc()->GetCallsEval() && !symScope->GetFunc()->GetChildCallsEval())
  1473. {
  1474. symScope->GetFunc()->GetParamScope()->SetIsObject();
  1475. symScope->GetFunc()->GetBodyScope()->SetIsObject();
  1476. }
  1477. }
  1478. }
  1479. return sym;
  1480. }
  1481. Symbol * ByteCodeGenerator::AddSymbolToScope(Scope *scope, const wchar_t *key, int keyLength, ParseNode *varDecl, SymbolType symbolType)
  1482. {
  1483. Symbol *sym = nullptr;
  1484. if (!UseParserBindings())
  1485. {
  1486. SymbolName const symName(key, keyLength);
  1487. if (scope->GetScopeType() == ScopeType_FunctionBody)
  1488. {
  1489. sym = scope->GetFunc()->GetParamScope()->FindLocalSymbol(symName);
  1490. }
  1491. if (sym == nullptr)
  1492. {
  1493. sym = scope->FindLocalSymbol(symName);
  1494. }
  1495. if (sym == nullptr)
  1496. {
  1497. sym = Anew(alloc, Symbol, symName, varDecl, symbolType);
  1498. scope->AddNewSymbol(sym);
  1499. #if DBG_DUMP
  1500. if (this->Trace())
  1501. {
  1502. Output::Print(L"added symbol %s of type %s to scope %x\n", key, sym->GetSymbolTypeName(), scope);
  1503. }
  1504. #endif
  1505. }
  1506. }
  1507. else
  1508. {
  1509. switch (varDecl->nop)
  1510. {
  1511. case knopConstDecl:
  1512. case knopLetDecl:
  1513. case knopVarDecl:
  1514. sym = varDecl->sxVar.sym/*New*/;
  1515. break;
  1516. case knopName:
  1517. AnalysisAssert(varDecl->sxPid.symRef);
  1518. sym = *varDecl->sxPid.symRef;
  1519. break;
  1520. default:
  1521. AnalysisAssert(0);
  1522. sym = nullptr;
  1523. break;
  1524. }
  1525. if (sym->GetScope() != scope && sym->GetScope()->GetScopeType() != ScopeType_Parameter)
  1526. {
  1527. // This can happen when we have a function declared at global eval scope, and it has
  1528. // references in deferred function bodies inside the eval. The BCG creates a new global scope
  1529. // on such compiles, so we essentially have to migrate the symbol to the new scope.
  1530. // We check fscrEvalCode, not fscrEval, because the same thing can happen in indirect eval,
  1531. // when fscrEval is not set.
  1532. Assert(((this->flags & fscrEvalCode) && sym->GetIsGlobal() && sym->GetSymbolType() == STFunction) || this->IsConsoleScopeEval());
  1533. Assert(scope->GetScopeType() == ScopeType_Global);
  1534. scope->AddNewSymbol(sym);
  1535. }
  1536. }
  1537. Assert(sym && sym->GetScope() && (sym->GetScope() == scope || sym->GetScope()->GetScopeType() == ScopeType_Parameter));
  1538. return sym;
  1539. }
  1540. Symbol * ByteCodeGenerator::AddSymbolToFunctionScope(const wchar_t *key, int keyLength, ParseNode *varDecl, SymbolType symbolType)
  1541. {
  1542. Scope* scope = currentScope->GetFunc()->GetBodyScope();
  1543. return this->AddSymbolToScope(scope, key, keyLength, varDecl, symbolType);
  1544. }
  1545. FuncInfo *ByteCodeGenerator::FindEnclosingNonLambda()
  1546. {
  1547. for (Scope *scope = TopFuncInfo()->GetBodyScope(); scope; scope = scope->GetEnclosingScope())
  1548. {
  1549. if (!scope->GetFunc()->IsLambda())
  1550. {
  1551. return scope->GetFunc();
  1552. }
  1553. }
  1554. Assert(0);
  1555. return nullptr;
  1556. }
  1557. bool ByteCodeGenerator::CanStackNestedFunc(FuncInfo * funcInfo, bool trace)
  1558. {
  1559. #if ENABLE_DEBUG_CONFIG_OPTIONS
  1560. wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  1561. #endif
  1562. Assert(!funcInfo->IsGlobalFunction());
  1563. bool const doStackNestedFunc = !funcInfo->HasMaybeEscapedNestedFunc() && !IsInDebugMode() && !funcInfo->byteCodeFunction->IsGenerator();
  1564. if (!doStackNestedFunc)
  1565. {
  1566. return false;
  1567. }
  1568. bool callsEval = funcInfo->GetCallsEval() || funcInfo->GetChildCallsEval();
  1569. if (callsEval)
  1570. {
  1571. if (trace)
  1572. {
  1573. PHASE_PRINT_TESTTRACE(Js::StackFuncPhase, funcInfo->byteCodeFunction,
  1574. L"HasMaybeEscapedNestedFunc (Eval): %s (function %s)\n",
  1575. funcInfo->byteCodeFunction->GetDisplayName(),
  1576. funcInfo->byteCodeFunction->GetDebugNumberSet(debugStringBuffer));
  1577. }
  1578. return false;
  1579. }
  1580. if (funcInfo->GetBodyScope()->GetIsObject() || funcInfo->GetParamScope()->GetIsObject())
  1581. {
  1582. if (trace)
  1583. {
  1584. PHASE_PRINT_TESTTRACE(Js::StackFuncPhase, funcInfo->byteCodeFunction,
  1585. L"HasMaybeEscapedNestedFunc (ObjectScope): %s (function %s)\n",
  1586. funcInfo->byteCodeFunction->GetDisplayName(),
  1587. funcInfo->byteCodeFunction->GetDebugNumberSet(debugStringBuffer));
  1588. }
  1589. return false;
  1590. }
  1591. if (trace && funcInfo->byteCodeFunction->GetNestedCount())
  1592. {
  1593. // Only print functions that actually have nested functions, although we will still mark
  1594. // functions that don't have nested child functions as DoStackNestedFunc.
  1595. PHASE_PRINT_TESTTRACE(Js::StackFuncPhase, funcInfo->byteCodeFunction,
  1596. L"DoStackNestedFunc: %s (function %s)\n",
  1597. funcInfo->byteCodeFunction->GetDisplayName(),
  1598. funcInfo->byteCodeFunction->GetDebugNumberSet(debugStringBuffer));
  1599. }
  1600. return !PHASE_OFF(Js::StackFuncPhase, funcInfo->byteCodeFunction);
  1601. }
  1602. bool ByteCodeGenerator::NeedObjectAsFunctionScope(FuncInfo * funcInfo, ParseNode * pnodeFnc) const
  1603. {
  1604. return funcInfo->GetCallsEval()
  1605. || funcInfo->GetChildCallsEval()
  1606. || NeedScopeObjectForArguments(funcInfo, pnodeFnc)
  1607. || (this->flags & (fscrEval | fscrImplicitThis | fscrImplicitParents));
  1608. }
  1609. Scope * ByteCodeGenerator::FindScopeForSym(Scope *symScope, Scope *scope, Js::PropertyId *envIndex, FuncInfo *funcInfo) const
  1610. {
  1611. for (scope = scope ? scope->GetEnclosingScope() : currentScope; scope; scope = scope->GetEnclosingScope())
  1612. {
  1613. if (scope->GetFunc() != funcInfo && scope->GetMustInstantiate() && scope != this->globalScope)
  1614. {
  1615. (*envIndex)++;
  1616. }
  1617. if (scope == symScope || scope->GetIsDynamic())
  1618. {
  1619. break;
  1620. }
  1621. }
  1622. Assert(scope);
  1623. return scope;
  1624. }
  1625. /* static */
  1626. Js::OpCode ByteCodeGenerator::GetStFldOpCode(FuncInfo* funcInfo, bool isRoot, bool isLetDecl, bool isConstDecl, bool isClassMemberInit)
  1627. {
  1628. return GetStFldOpCode(funcInfo->GetIsStrictMode(), isRoot, isLetDecl, isConstDecl, isClassMemberInit);
  1629. }
  1630. /* static */
  1631. Js::OpCode ByteCodeGenerator::GetScopedStFldOpCode(FuncInfo* funcInfo, bool isConsoleScopeLetConst)
  1632. {
  1633. if (isConsoleScopeLetConst)
  1634. {
  1635. return Js::OpCode::ConsoleScopedStFld;
  1636. }
  1637. return GetScopedStFldOpCode(funcInfo->GetIsStrictMode());
  1638. }
  1639. /* static */
  1640. Js::OpCode ByteCodeGenerator::GetStElemIOpCode(FuncInfo* funcInfo)
  1641. {
  1642. return GetStElemIOpCode(funcInfo->GetIsStrictMode());
  1643. }
  1644. bool ByteCodeGenerator::DoJitLoopBodies(FuncInfo *funcInfo) const
  1645. {
  1646. // Never JIT loop bodies in a function with a try.
  1647. // Otherwise, always JIT loop bodies under /forcejitloopbody.
  1648. // Otherwise, JIT loop bodies unless we're in eval/"new Function" or feature is disabled.
  1649. Assert(funcInfo->byteCodeFunction->IsFunctionParsed());
  1650. Js::FunctionBody* functionBody = funcInfo->byteCodeFunction->GetFunctionBody();
  1651. return functionBody->ForceJITLoopBody() || funcInfo->byteCodeFunction->IsJitLoopBodyPhaseEnabled();
  1652. }
  1653. void ByteCodeGenerator::Generate(__in ParseNode *pnode, ulong grfscr, __in ByteCodeGenerator* byteCodeGenerator,
  1654. __inout Js::ParseableFunctionInfo ** ppRootFunc, __in uint sourceIndex,
  1655. __in bool forceNoNative, __in Parser* parser, Js::ScriptFunction **functionRef)
  1656. {
  1657. Js::ScriptContext * scriptContext = byteCodeGenerator->scriptContext;
  1658. #ifdef PROFILE_EXEC
  1659. scriptContext->ProfileBegin(Js::ByteCodePhase);
  1660. #endif
  1661. JS_ETW(EventWriteJSCRIPT_BYTECODEGEN_START(scriptContext, 0));
  1662. ThreadContext * threadContext = scriptContext->GetThreadContext();
  1663. Js::Utf8SourceInfo * utf8SourceInfo = scriptContext->GetSource(sourceIndex);
  1664. byteCodeGenerator->m_utf8SourceInfo = utf8SourceInfo;
  1665. // For dynamic code, just provide a small number since that source info should have very few functions
  1666. // For static code, the nextLocalFunctionId is a good guess of the initial size of the array to minimize reallocs
  1667. SourceContextInfo * sourceContextInfo = utf8SourceInfo->GetSrcInfo()->sourceContextInfo;
  1668. utf8SourceInfo->EnsureInitialized((grfscr & fscrDynamicCode) ? 4 : (sourceContextInfo->nextLocalFunctionId - pnode->sxFnc.functionId));
  1669. sourceContextInfo->EnsureInitialized();
  1670. ArenaAllocator localAlloc(L"ByteCode", threadContext->GetPageAllocator(), Js::Throw::OutOfMemory);
  1671. byteCodeGenerator->parser = parser;
  1672. byteCodeGenerator->SetCurrentSourceIndex(sourceIndex);
  1673. byteCodeGenerator->Begin(&localAlloc, grfscr, *ppRootFunc);
  1674. byteCodeGenerator->functionRef = functionRef;
  1675. Visit(pnode, byteCodeGenerator, Bind, AssignRegisters);
  1676. byteCodeGenerator->forceNoNative = forceNoNative;
  1677. byteCodeGenerator->EmitProgram(pnode);
  1678. if (byteCodeGenerator->flags & fscrEval)
  1679. {
  1680. // The eval caller's frame always escapes if eval refers to the caller's arguments.
  1681. byteCodeGenerator->GetRootFunc()->GetFunctionBody()->SetFuncEscapes(
  1682. byteCodeGenerator->funcEscapes || pnode->sxProg.m_UsesArgumentsAtGlobal);
  1683. }
  1684. #ifdef IR_VIEWER
  1685. if (grfscr & fscrIrDumpEnable)
  1686. {
  1687. byteCodeGenerator->GetRootFunc()->GetFunctionBody()->SetIRDumpEnabled(true);
  1688. }
  1689. #endif /* IR_VIEWER */
  1690. byteCodeGenerator->CheckDeferParseHasMaybeEscapedNestedFunc();
  1691. #ifdef PROFILE_EXEC
  1692. scriptContext->ProfileEnd(Js::ByteCodePhase);
  1693. #endif
  1694. JS_ETW(EventWriteJSCRIPT_BYTECODEGEN_STOP(scriptContext, 0));
  1695. #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_PREJIT)
  1696. if (!byteCodeGenerator->forceNoNative && !scriptContext->GetConfig()->IsNoNative()
  1697. && Js::Configuration::Global.flags.Prejit
  1698. && (grfscr & fscrNoPreJit) == 0)
  1699. {
  1700. GenerateAllFunctions(scriptContext->GetNativeCodeGenerator(), byteCodeGenerator->GetRootFunc()->GetFunctionBody());
  1701. }
  1702. #endif
  1703. if (ppRootFunc)
  1704. {
  1705. *ppRootFunc = byteCodeGenerator->GetRootFunc();
  1706. }
  1707. #ifdef PERF_COUNTERS
  1708. PHASE_PRINT_TESTTRACE1(Js::DeferParsePhase, L"TestTrace: deferparse - # of func: %d # deferparsed: %d\n",
  1709. PerfCounter::CodeCounterSet::GetTotalFunctionCounter().GetValue(), PerfCounter::CodeCounterSet::GetDeferredFunctionCounter().GetValue());
  1710. #endif
  1711. }
  1712. void ByteCodeGenerator::CheckDeferParseHasMaybeEscapedNestedFunc()
  1713. {
  1714. if (!this->parentScopeInfo)
  1715. {
  1716. return;
  1717. }
  1718. Assert(CONFIG_FLAG(DeferNested));
  1719. Assert(this->funcInfoStack && !this->funcInfoStack->Empty());
  1720. // Box the stack nested function if we detected new may be escaped use function.
  1721. SList<FuncInfo *>::Iterator i(this->funcInfoStack);
  1722. bool succeed = i.Next();
  1723. Assert(succeed);
  1724. Assert(i.Data()->IsGlobalFunction()); // We always leave a glo on type when defer parsing.
  1725. Assert(!i.Data()->IsRestored());
  1726. succeed = i.Next();
  1727. FuncInfo * top = i.Data();
  1728. Assert(!top->IsGlobalFunction());
  1729. Assert(top->IsRestored());
  1730. Js::FunctionBody * rootFuncBody = this->GetRootFunc()->GetFunctionBody();
  1731. if (!rootFuncBody->DoStackNestedFunc())
  1732. {
  1733. top->SetHasMaybeEscapedNestedFunc(DebugOnly(L"DeferredChild"));
  1734. }
  1735. else
  1736. {
  1737. // We have to wait until it is parsed before we populate the stack nested func parent.
  1738. Js::FunctionBody * parentFunctionBody = nullptr;
  1739. FuncInfo * parentFunc = top->GetBodyScope()->GetEnclosingFunc();
  1740. if (!parentFunc->IsGlobalFunction())
  1741. {
  1742. parentFunctionBody = parentFunc->GetParsedFunctionBody();
  1743. Assert(parentFunctionBody != rootFuncBody);
  1744. if (parentFunctionBody->DoStackNestedFunc())
  1745. {
  1746. rootFuncBody->SetStackNestedFuncParent(parentFunctionBody);
  1747. }
  1748. }
  1749. }
  1750. do
  1751. {
  1752. FuncInfo * funcInfo = i.Data();
  1753. Assert(funcInfo->IsRestored());
  1754. Js::FunctionBody * functionBody = funcInfo->GetParsedFunctionBody();
  1755. bool didStackNestedFunc = functionBody->DoStackNestedFunc();
  1756. if (!didStackNestedFunc)
  1757. {
  1758. return;
  1759. }
  1760. if (funcInfo->HasMaybeEscapedNestedFunc())
  1761. {
  1762. // This should box the rest of the parent functions.
  1763. if (PHASE_TESTTRACE(Js::StackFuncPhase, this->pCurrentFunction))
  1764. {
  1765. wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  1766. Output::Print(L"DeferParse: box and disable stack function: %s (function %s)\n",
  1767. functionBody->GetDisplayName(), functionBody->GetDebugNumberSet(debugStringBuffer));
  1768. Output::Flush();
  1769. }
  1770. // During the box workflow we reset all the parents of all nested functions and up. If a fault occurs when the stack function
  1771. // is created this will cause further issues when trying to use the function object again. So failing faster seems to make more sense.
  1772. try
  1773. {
  1774. Js::StackScriptFunction::Box(functionBody, functionRef);
  1775. }
  1776. catch (Js::OutOfMemoryException)
  1777. {
  1778. FailedToBox_OOM_fatal_error((ULONG_PTR)functionBody);
  1779. }
  1780. return;
  1781. }
  1782. }
  1783. while (i.Next());
  1784. }
  1785. void ByteCodeGenerator::Begin(
  1786. __in ArenaAllocator *alloc,
  1787. __in ulong grfscr,
  1788. __in Js::ParseableFunctionInfo* pRootFunc)
  1789. {
  1790. this->alloc = alloc;
  1791. this->flags = grfscr;
  1792. this->pRootFunc = pRootFunc;
  1793. this->pCurrentFunction = pRootFunc ? pRootFunc->GetFunctionBody() : nullptr;
  1794. if (this->pCurrentFunction && this->pCurrentFunction->GetIsGlobalFunc() && IsInNonDebugMode())
  1795. {
  1796. // This is the deferred parse case (not due to debug mode), in which case the global function will not be marked to compiled again.
  1797. this->pCurrentFunction = nullptr;
  1798. }
  1799. this->globalScope = nullptr;
  1800. this->currentScope = nullptr;
  1801. this->currentBlock = nullptr;
  1802. this->isBinding = true;
  1803. this->inPrologue = false;
  1804. this->funcEscapes = false;
  1805. this->maxAstSize = 0;
  1806. this->loopDepth = 0;
  1807. this->envDepth = 0;
  1808. this->trackEnvDepth = false;
  1809. this->funcInfoStack = Anew(alloc, SList<FuncInfo*>, alloc);
  1810. // If pRootFunc is not null, this is a deferred parse function
  1811. // so reuse the property record list bound there since some of the symbols could have
  1812. // been bound. If it's null, we need to create a new property record list
  1813. if (pRootFunc != nullptr)
  1814. {
  1815. this->propertyRecords = pRootFunc->GetBoundPropertyRecords();
  1816. }
  1817. else
  1818. {
  1819. this->propertyRecords = nullptr;
  1820. }
  1821. Js::FunctionBody *fakeGlobalFunc = scriptContext->GetFakeGlobalFuncForUndefer();
  1822. if (fakeGlobalFunc)
  1823. {
  1824. fakeGlobalFunc->ClearBoundPropertyRecords();
  1825. }
  1826. }
  1827. HRESULT GenerateByteCode(__in ParseNode *pnode, __in ulong grfscr, __in Js::ScriptContext* scriptContext, __inout Js::ParseableFunctionInfo ** ppRootFunc,
  1828. __in uint sourceIndex, __in bool forceNoNative, __in Parser* parser, __in CompileScriptException *pse, Js::ScopeInfo* parentScopeInfo,
  1829. Js::ScriptFunction ** functionRef)
  1830. {
  1831. HRESULT hr = S_OK;
  1832. ByteCodeGenerator byteCodeGenerator(scriptContext, parentScopeInfo);
  1833. BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT_NESTED
  1834. {
  1835. // Main code.
  1836. ByteCodeGenerator::Generate(pnode, grfscr, &byteCodeGenerator, ppRootFunc, sourceIndex, forceNoNative, parser, functionRef);
  1837. }
  1838. END_TRANSLATE_EXCEPTION_TO_HRESULT(hr);
  1839. if (FAILED(hr))
  1840. {
  1841. hr = pse->ProcessError(nullptr, hr, nullptr);
  1842. }
  1843. return hr;
  1844. }
  1845. void BindInstAndMember(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  1846. {
  1847. Assert(pnode->nop == knopDot);
  1848. BindReference(pnode, byteCodeGenerator);
  1849. ParseNode *right = pnode->sxBin.pnode2;
  1850. Assert(right->nop == knopName);
  1851. byteCodeGenerator->AssignPropertyId(right->sxPid.pid);
  1852. right->sxPid.sym = nullptr;
  1853. right->sxPid.symRef = nullptr;
  1854. right->grfpn |= fpnMemberReference;
  1855. }
  1856. void BindReference(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  1857. {
  1858. // Do special reference-op binding so that we can, for instance, handle call from inside "with"
  1859. // where the "this" instance must be found dynamically.
  1860. bool isCallNode = false;
  1861. bool funcEscapes = false;
  1862. switch (pnode->nop)
  1863. {
  1864. case knopCall:
  1865. isCallNode = true;
  1866. pnode = pnode->sxCall.pnodeTarget;
  1867. break;
  1868. case knopDelete:
  1869. case knopTypeof:
  1870. pnode = pnode->sxUni.pnode1;
  1871. break;
  1872. case knopDot:
  1873. case knopIndex:
  1874. funcEscapes = true;
  1875. // fall through
  1876. case knopAsg:
  1877. pnode = pnode->sxBin.pnode1;
  1878. break;
  1879. default:
  1880. AssertMsg(0, "Unexpected opcode in BindReference");
  1881. return;
  1882. }
  1883. if (pnode->nop == knopName)
  1884. {
  1885. pnode->sxPid.sym = byteCodeGenerator->FindSymbol(pnode->sxPid.symRef, pnode->sxPid.pid, isCallNode);
  1886. if (funcEscapes &&
  1887. pnode->sxPid.sym &&
  1888. pnode->sxPid.sym->GetSymbolType() == STFunction &&
  1889. (!pnode->sxPid.sym->GetIsGlobal() || (byteCodeGenerator->GetFlags() & fscrEval)))
  1890. {
  1891. // Dot, index, and scope ops can cause a local function on the LHS to escape.
  1892. // Make sure scopes are not cached in this case.
  1893. byteCodeGenerator->FuncEscapes(pnode->sxPid.sym->GetScope());
  1894. }
  1895. }
  1896. }
  1897. void MarkFormal(ByteCodeGenerator *byteCodeGenerator, Symbol *formal, bool assignLocation, bool needDeclaration)
  1898. {
  1899. if (assignLocation)
  1900. {
  1901. formal->SetLocation(byteCodeGenerator->NextVarRegister());
  1902. }
  1903. if (needDeclaration)
  1904. {
  1905. formal->SetNeedDeclaration(true);
  1906. }
  1907. }
  1908. void AddArgsToScope(ParseNodePtr pnode, ByteCodeGenerator *byteCodeGenerator, bool assignLocation)
  1909. {
  1910. Assert(byteCodeGenerator->TopFuncInfo()->varRegsCount == 0);
  1911. Js::ArgSlot pos = 1;
  1912. bool isSimpleParameterList = pnode->sxFnc.IsSimpleParameterList();
  1913. auto addArgToScope = [&](ParseNode *arg)
  1914. {
  1915. if (arg->IsVarLetOrConst())
  1916. {
  1917. Symbol *formal = byteCodeGenerator->AddSymbolToScope(byteCodeGenerator->TopFuncInfo()->GetParamScope(),
  1918. reinterpret_cast<const wchar_t*>(arg->sxVar.pid->Psz()),
  1919. arg->sxVar.pid->Cch(),
  1920. arg,
  1921. STFormal);
  1922. #if DBG_DUMP
  1923. if (byteCodeGenerator->Trace())
  1924. {
  1925. Output::Print(L"current context has declared arg %s of type %s at position %d\n", arg->sxVar.pid->Psz(), formal->GetSymbolTypeName(), pos);
  1926. }
  1927. #endif
  1928. if (!isSimpleParameterList)
  1929. {
  1930. formal->SetIsNonSimpleParameter(true);
  1931. }
  1932. arg->sxVar.sym = formal;
  1933. MarkFormal(byteCodeGenerator, formal, assignLocation || !isSimpleParameterList, !isSimpleParameterList);
  1934. }
  1935. else if (arg->nop == knopParamPattern)
  1936. {
  1937. arg->sxParamPattern.location = byteCodeGenerator->NextVarRegister();
  1938. }
  1939. else
  1940. {
  1941. Assert(false);
  1942. }
  1943. UInt16Math::Inc(pos);
  1944. };
  1945. // We process rest separately because the number of in args needs to exclude rest.
  1946. MapFormalsWithoutRest(pnode, addArgToScope);
  1947. byteCodeGenerator->SetNumberOfInArgs(pos);
  1948. MapFormalsFromPattern(pnode, addArgToScope);
  1949. if (pnode->sxFnc.pnodeRest != nullptr)
  1950. {
  1951. // The rest parameter will always be in a register, regardless of whether it is in a scope slot.
  1952. // We save the assignLocation value for the assert condition below.
  1953. bool assignLocationSave = assignLocation;
  1954. assignLocation = true;
  1955. addArgToScope(pnode->sxFnc.pnodeRest);
  1956. assignLocation = assignLocationSave;
  1957. }
  1958. Assert(!assignLocation || byteCodeGenerator->TopFuncInfo()->varRegsCount + 1 == pos);
  1959. }
  1960. void AddVarsToScope(ParseNode *vars, ByteCodeGenerator *byteCodeGenerator)
  1961. {
  1962. while (vars != nullptr)
  1963. {
  1964. Symbol *sym = nullptr;
  1965. if (!byteCodeGenerator->UseParserBindings()
  1966. && byteCodeGenerator->GetCurrentScope()->GetFunc()->GetParamScope() != nullptr)
  1967. {
  1968. SymbolName const symName(reinterpret_cast<const wchar_t*>(vars->sxVar.pid->Psz()), vars->sxVar.pid->Cch());
  1969. // If we are not using parser bindings, we need to check that the sym is not in the parameter scope before adding it.
  1970. // Fetch the sym we just added from the param scope.
  1971. sym = byteCodeGenerator->GetCurrentScope()->GetFunc()->GetParamScope()->FindLocalSymbol(symName);
  1972. // Arguments needs to be created at parameter scope.
  1973. if (sym == nullptr && vars->grfpn & PNodeFlags::fpnArguments)
  1974. {
  1975. Scope* scope = byteCodeGenerator->GetCurrentScope()->GetFunc()->GetParamScope();
  1976. sym = byteCodeGenerator->AddSymbolToScope(scope, reinterpret_cast<const wchar_t*>(vars->sxVar.pid->Psz()), vars->sxVar.pid->Cch(), vars, STVariable);
  1977. }
  1978. }
  1979. if (sym == nullptr)
  1980. {
  1981. sym = byteCodeGenerator->AddSymbolToFunctionScope(reinterpret_cast<const wchar_t*>(vars->sxVar.pid->Psz()), vars->sxVar.pid->Cch(), vars, STVariable);
  1982. }
  1983. #if DBG_DUMP
  1984. if (sym->GetSymbolType() == STVariable && byteCodeGenerator->Trace())
  1985. {
  1986. Output::Print(L"current context has declared var %s of type %s\n",
  1987. vars->sxVar.pid->Psz(), sym->GetSymbolTypeName());
  1988. }
  1989. #endif
  1990. if (sym->GetIsArguments() || vars->sxVar.pnodeInit == nullptr)
  1991. {
  1992. // LHS's of var decls are usually bound to symbols later, during the Visit/Bind pass,
  1993. // so that things like catch scopes can be taken into account.
  1994. // The exception is "arguments", which always binds to the local scope.
  1995. // We can also bind to the function scope symbol now if there's no init value
  1996. // to assign.
  1997. vars->sxVar.sym = sym;
  1998. if (sym->GetIsArguments())
  1999. {
  2000. byteCodeGenerator->TopFuncInfo()->SetArgumentsSymbol(sym);
  2001. }
  2002. }
  2003. else
  2004. {
  2005. vars->sxVar.sym = nullptr;
  2006. }
  2007. vars = vars->sxVar.pnodeNext;
  2008. }
  2009. }
  2010. template <class Fn>
  2011. void VisitFncDecls(ParseNode *fns, Fn action)
  2012. {
  2013. while (fns != nullptr)
  2014. {
  2015. switch (fns->nop)
  2016. {
  2017. case knopFncDecl:
  2018. action(fns);
  2019. fns = fns->sxFnc.pnodeNext;
  2020. break;
  2021. case knopBlock:
  2022. fns = fns->sxBlock.pnodeNext;
  2023. break;
  2024. case knopCatch:
  2025. fns = fns->sxCatch.pnodeNext;
  2026. break;
  2027. case knopWith:
  2028. fns = fns->sxWith.pnodeNext;
  2029. break;
  2030. default:
  2031. AssertMsg(false, "Unexpected opcode in tree of scopes");
  2032. return;
  2033. }
  2034. }
  2035. }
  2036. FuncInfo* PreVisitFunction(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator)
  2037. {
  2038. // Do binding of function name(s), initialize function scope, propagate function-wide properties from
  2039. // the parent (if any).
  2040. FuncInfo* parentFunc = byteCodeGenerator->TopFuncInfo();
  2041. // fIsRoot indicates that this is the root function to be returned to a ParseProcedureText/AddScriptLet/etc. call.
  2042. // In such cases, the global function is just a wrapper around the root function's declaration.
  2043. // We used to assert that this was the only top-level function body, but it's possible to trick
  2044. // "new Function" into compiling more than one function (see WOOB 1121759).
  2045. bool fIsRoot = (!(byteCodeGenerator->GetFlags() & fscrGlobalCode) &&
  2046. parentFunc->IsGlobalFunction() &&
  2047. parentFunc->root->sxFnc.GetTopLevelScope() == pnode);
  2048. const wchar_t *funcName = Js::Constants::AnonymousFunction;
  2049. uint funcNameLength = Js::Constants::AnonymousFunctionLength;
  2050. uint functionNameOffset = 0;
  2051. bool funcExprWithName = false;
  2052. if (pnode->sxFnc.hint != nullptr)
  2053. {
  2054. funcName = reinterpret_cast<const wchar_t*>(pnode->sxFnc.hint);
  2055. funcNameLength = pnode->sxFnc.hintLength;
  2056. functionNameOffset = pnode->sxFnc.hintOffset;
  2057. Assert(funcNameLength != 0 || funcNameLength == (int)wcslen(funcName));
  2058. }
  2059. if (pnode->sxFnc.IsDeclaration() || pnode->sxFnc.IsMethod())
  2060. {
  2061. // Class members have the fully qualified name stored in 'hint', no need to replace it.
  2062. if (pnode->sxFnc.pid && !pnode->sxFnc.IsClassMember())
  2063. {
  2064. funcName = reinterpret_cast<const wchar_t*>(pnode->sxFnc.pid->Psz());
  2065. funcNameLength = pnode->sxFnc.pid->Cch();
  2066. functionNameOffset = 0;
  2067. }
  2068. }
  2069. else if ((pnode->sxFnc.pnodeName != nullptr) &&
  2070. (pnode->sxFnc.pnodeName->nop == knopVarDecl))
  2071. {
  2072. funcName = reinterpret_cast<const wchar_t*>(pnode->sxFnc.pnodeName->sxVar.pid->Psz());
  2073. funcNameLength = pnode->sxFnc.pnodeName->sxVar.pid->Cch();
  2074. functionNameOffset = 0;
  2075. //
  2076. // create the new scope for Function expression only in ES5 mode
  2077. //
  2078. funcExprWithName = true;
  2079. }
  2080. if (byteCodeGenerator->Trace())
  2081. {
  2082. Output::Print(L"function start %s\n", funcName);
  2083. }
  2084. Assert(pnode->sxFnc.funcInfo == nullptr);
  2085. FuncInfo* funcInfo = pnode->sxFnc.funcInfo = byteCodeGenerator->StartBindFunction(funcName, funcNameLength, functionNameOffset, &funcExprWithName, pnode);
  2086. funcInfo->byteCodeFunction->SetIsNamedFunctionExpression(funcExprWithName);
  2087. funcInfo->byteCodeFunction->SetIsNameIdentifierRef(pnode->sxFnc.isNameIdentifierRef);
  2088. if (fIsRoot)
  2089. {
  2090. byteCodeGenerator->SetRootFuncInfo(funcInfo);
  2091. }
  2092. if (pnode->sxFnc.pnodeBody == nullptr)
  2093. {
  2094. // This is a deferred byte code gen, so we're done.
  2095. // Process the formal arguments, even if there's no AST for the body, to support Function.length.
  2096. if (byteCodeGenerator->UseParserBindings())
  2097. {
  2098. Js::ArgSlot pos = 1;
  2099. // We skip the rest parameter here because it is not counted towards the in arg count.
  2100. MapFormalsWithoutRest(pnode, [&](ParseNode *pnode) { UInt16Math::Inc(pos); });
  2101. byteCodeGenerator->SetNumberOfInArgs(pos);
  2102. }
  2103. else
  2104. {
  2105. AddArgsToScope(pnode, byteCodeGenerator, false);
  2106. }
  2107. return funcInfo;
  2108. }
  2109. if (pnode->sxFnc.HasReferenceableBuiltInArguments())
  2110. {
  2111. // The parser identified that there is a way to reference the built-in 'arguments' variable from this function. So, we
  2112. // need to determine whether we need to create the variable or not. We need to create the variable iff:
  2113. if (pnode->sxFnc.CallsEval())
  2114. {
  2115. // 1. eval is called.
  2116. // 2. when the debugging is enabled, since user can seek arguments during breakpoint.
  2117. funcInfo->SetHasArguments(true);
  2118. funcInfo->SetHasHeapArguments(true);
  2119. if (funcInfo->inArgsCount == 0)
  2120. {
  2121. // If no formals to function, no need to create the propertyid array
  2122. byteCodeGenerator->AssignNullConstRegister();
  2123. }
  2124. }
  2125. else if (pnode->sxFnc.UsesArguments())
  2126. {
  2127. // 3. the function directly references an 'arguments' identifier
  2128. funcInfo->SetHasArguments(true);
  2129. if (pnode->sxFnc.HasHeapArguments())
  2130. {
  2131. funcInfo->SetHasHeapArguments(true, !pnode->sxFnc.IsGenerator() /*= Optimize arguments in backend*/);
  2132. if (funcInfo->inArgsCount == 0)
  2133. {
  2134. // If no formals to function, no need to create the propertyid array
  2135. byteCodeGenerator->AssignNullConstRegister();
  2136. }
  2137. }
  2138. }
  2139. }
  2140. Js::FunctionBody* parentFunctionBody = parentFunc->GetParsedFunctionBody();
  2141. if (funcInfo->GetHasArguments() ||
  2142. parentFunctionBody->GetHasOrParentHasArguments())
  2143. {
  2144. // The JIT uses this info, for instance, to narrow kills of array operations
  2145. funcInfo->GetParsedFunctionBody()->SetHasOrParentHasArguments(true);
  2146. }
  2147. PreVisitBlock(pnode->sxFnc.pnodeScopes, byteCodeGenerator);
  2148. // If we have arguments, we are going to need locations if the function is in strict mode or we have a non-simple parameter list. This is because we will not create a scope object.
  2149. bool assignLocationForFormals = !(funcInfo->GetHasHeapArguments() && ByteCodeGenerator::NeedScopeObjectForArguments(funcInfo, funcInfo->root));
  2150. AddArgsToScope(pnode, byteCodeGenerator, assignLocationForFormals);
  2151. PreVisitBlock(pnode->sxFnc.pnodeBodyScope, byteCodeGenerator);
  2152. AddVarsToScope(pnode->sxFnc.pnodeVars, byteCodeGenerator);
  2153. return funcInfo;
  2154. }
  2155. void AssignFuncSymRegister(ParseNode * pnode, ByteCodeGenerator * byteCodeGenerator, FuncInfo * callee)
  2156. {
  2157. // register to hold the allocated function (in enclosing sequence of global statements)
  2158. // TODO: Make the parser identify uses of function decls as RHS's of expressions.
  2159. // Currently they're all marked as used, so they all get permanent (non-temp) registers.
  2160. if (pnode->sxFnc.pnodeName == nullptr)
  2161. {
  2162. return;
  2163. }
  2164. Assert(pnode->sxFnc.pnodeName->nop == knopVarDecl);
  2165. Symbol *sym = pnode->sxFnc.pnodeName->sxVar.sym;
  2166. if (sym)
  2167. {
  2168. if (!sym->GetIsGlobal() && !(callee->funcExprScope && callee->funcExprScope->GetIsObject()))
  2169. {
  2170. // If the func decl is used, we have to give the expression a register to protect against:
  2171. // x.x = function f() {...};
  2172. // x.y = function f() {...};
  2173. // If we let the value reside in the local slot for f, then both assignments will get the
  2174. // second definition.
  2175. if (!pnode->sxFnc.IsDeclaration())
  2176. {
  2177. // A named function expression's name belongs to the enclosing scope.
  2178. // In ES5 mode, it is visible only inside the inner function.
  2179. // Allocate a register for the 'name' symbol from an appropriate register namespace.
  2180. if (callee->GetFuncExprNameReference())
  2181. {
  2182. // This is a function expression with a name, but probably doesn't have a use within
  2183. // the function. If that is the case then allocate a register for LdFuncExpr inside the function
  2184. // we just finished post-visiting.
  2185. if (sym->GetLocation() == Js::Constants::NoRegister)
  2186. {
  2187. sym->SetLocation(callee->NextVarRegister());
  2188. }
  2189. }
  2190. }
  2191. else
  2192. {
  2193. // Function declaration
  2194. byteCodeGenerator->AssignRegister(sym);
  2195. pnode->location = sym->GetLocation();
  2196. Assert(byteCodeGenerator->GetCurrentScope()->GetFunc() == sym->GetScope()->GetFunc());
  2197. Symbol * functionScopeVarSym = sym->GetFuncScopeVarSym();
  2198. if (functionScopeVarSym &&
  2199. !functionScopeVarSym->GetIsGlobal() &&
  2200. !functionScopeVarSym->IsInSlot(sym->GetScope()->GetFunc()))
  2201. {
  2202. Assert(byteCodeGenerator->GetScriptContext()->GetConfig()->IsBlockScopeEnabled());
  2203. byteCodeGenerator->AssignRegister(functionScopeVarSym);
  2204. }
  2205. }
  2206. }
  2207. else if (!pnode->sxFnc.IsDeclaration())
  2208. {
  2209. if (sym->GetLocation() == Js::Constants::NoRegister)
  2210. {
  2211. // Here, we are assigning a register for the LdFuncExpr instruction inside the function we just finished
  2212. // post-visiting. The symbol is given a register from the register pool for the function we just finished
  2213. // post-visiting, rather than from the parent function's register pool.
  2214. sym->SetLocation(callee->NextVarRegister());
  2215. }
  2216. }
  2217. }
  2218. }
  2219. FuncInfo* PostVisitFunction(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator)
  2220. {
  2221. // Assign function-wide registers such as local frame object, closure environment, etc., based on
  2222. // observed attributes. Propagate attributes to the parent function (if any).
  2223. FuncInfo *top = byteCodeGenerator->TopFuncInfo();
  2224. Symbol *sym = pnode->sxFnc.GetFuncSymbol();
  2225. bool funcExprWithName = !top->IsGlobalFunction() && sym && sym->GetFuncExpr();
  2226. if (top->IsLambda())
  2227. {
  2228. if (byteCodeGenerator->FindEnclosingNonLambda()->isThisLexicallyCaptured)
  2229. {
  2230. top->byteCodeFunction->SetCapturesThis();
  2231. }
  2232. }
  2233. // If this is a named function expression and has deferred child, mark has non-local reference.
  2234. if (funcExprWithName)
  2235. {
  2236. // If we are reparsing this function due to being in debug mode - we should restore the state of this from the earlier parse
  2237. if (top->byteCodeFunction->IsFunctionParsed() && top->GetParsedFunctionBody()->HasFuncExprNameReference())
  2238. {
  2239. top->SetFuncExprNameReference(true);
  2240. sym->SetHasNonLocalReference(true, byteCodeGenerator);
  2241. top->SetHasLocalInClosure(true);
  2242. }
  2243. else if (top->HasDeferredChild())
  2244. {
  2245. // Before doing this, though, make sure there's no local symbol that hides the function name
  2246. // from the nested functions. If a lookup starting at the current local scope finds some symbol
  2247. // other than the func expr, then it's hidden. (See Win8 393618.)
  2248. Assert(CONFIG_FLAG(DeferNested));
  2249. sym->SetHasNonLocalReference(true, byteCodeGenerator);
  2250. top->SetHasLocalInClosure(true);
  2251. if (pnode->sxFnc.pnodeBody)
  2252. {
  2253. top->GetParsedFunctionBody()->SetAllNonLocalReferenced(true);
  2254. }
  2255. if (!top->root->sxFnc.NameIsHidden())
  2256. {
  2257. top->SetFuncExprNameReference(true);
  2258. if (pnode->sxFnc.pnodeBody)
  2259. {
  2260. top->GetParsedFunctionBody()->SetFuncExprNameReference(true);
  2261. }
  2262. top->GetBodyScope()->SetIsObject();
  2263. top->GetParamScope()->SetIsObject();
  2264. if (pnode->sxFnc.pnodeBody)
  2265. {
  2266. top->GetParsedFunctionBody()->SetHasSetIsObject(true);
  2267. }
  2268. }
  2269. }
  2270. }
  2271. if (pnode->nop != knopProg
  2272. && !top->bodyScope->GetIsObject()
  2273. && byteCodeGenerator->NeedObjectAsFunctionScope(top, pnode))
  2274. {
  2275. // Even if it wasn't determined during visiting this function that we need a scope object, we still have a few conditions that may require one.
  2276. top->bodyScope->SetIsObject();
  2277. }
  2278. if (pnode->nop == knopProg
  2279. && top->byteCodeFunction->GetIsStrictMode()
  2280. && (byteCodeGenerator->GetFlags() & fscrEval))
  2281. {
  2282. // At global scope inside a strict mode eval, vars will not leak out and require a scope object (along with its parent.)
  2283. top->bodyScope->SetIsObject();
  2284. }
  2285. if (pnode->sxFnc.pnodeBody)
  2286. {
  2287. if (!top->IsGlobalFunction())
  2288. {
  2289. PostVisitBlock(pnode->sxFnc.pnodeBodyScope, byteCodeGenerator);
  2290. PostVisitBlock(pnode->sxFnc.pnodeScopes, byteCodeGenerator);
  2291. }
  2292. if ((byteCodeGenerator->GetFlags() & fscrEvalCode) && top->GetCallsEval())
  2293. {
  2294. // Must establish "this" in case nested eval refers to it.
  2295. top->GetParsedFunctionBody()->SetHasThis(true);
  2296. }
  2297. // This function refers to the closure environment if:
  2298. // 1. it has a child function (we'll pass the environment to the constructor when the child is created -
  2299. // even if it's not needed, it's as cheap as loading "null" from the library);
  2300. // 2. it calls eval (and will use the environment to construct the scope chain to pass to eval);
  2301. // 3. it refers to a local defined in a parent function;
  2302. // 4. it refers to a global and some parent calls eval (which might declare the "global" locally);
  2303. // 5. it refers to a global and we're in an event handler;
  2304. // 6. it refers to a global and the function was declared inside a "with";
  2305. // 7. it refers to a global and we're in an eval expression.
  2306. if (pnode->sxFnc.nestedCount != 0 ||
  2307. top->GetCallsEval() ||
  2308. top->GetHasClosureReference() ||
  2309. ((top->GetHasGlobalRef() &&
  2310. (byteCodeGenerator->InDynamicScope() ||
  2311. (byteCodeGenerator->GetFlags() & (fscrImplicitThis | fscrImplicitParents | fscrEval))))))
  2312. {
  2313. byteCodeGenerator->SetNeedEnvRegister();
  2314. if (top->GetIsEventHandler())
  2315. {
  2316. byteCodeGenerator->AssignThisRegister();
  2317. }
  2318. }
  2319. // This function needs to construct a local frame on the heap if it is not the global function (even in eval) and:
  2320. // 1. it calls eval, which may refer to or declare any locals in this frame;
  2321. // 2. a child calls eval (which may refer to locals through a closure);
  2322. // 3. it uses non-strict mode "arguments", so the arguments have to be put in a closure;
  2323. // 4. it defines a local that is used by a child function (read from a closure).
  2324. // 5. it is a main function that's wrapped in a function expression scope but has locals used through
  2325. // a closure (used in forReference function call cases in a with for example).
  2326. if (!top->IsGlobalFunction())
  2327. {
  2328. if (top->GetCallsEval() ||
  2329. top->GetChildCallsEval() ||
  2330. (top->GetHasArguments() && ByteCodeGenerator::NeedScopeObjectForArguments(top, pnode) && pnode->sxFnc.pnodeArgs != nullptr) ||
  2331. top->GetHasLocalInClosure() ||
  2332. top->funcExprScope && top->funcExprScope->GetMustInstantiate())
  2333. {
  2334. if (!top->GetCallsEval())
  2335. {
  2336. byteCodeGenerator->AssignFrameSlotsRegister();
  2337. }
  2338. if (byteCodeGenerator->NeedObjectAsFunctionScope(top, top->root)
  2339. || top->bodyScope->GetIsObject()
  2340. || top->paramScope->GetIsObject())
  2341. {
  2342. byteCodeGenerator->AssignFrameObjRegister();
  2343. }
  2344. // The function also needs to construct a frame display if:
  2345. // 1. it calls eval;
  2346. // 2. it has a child function.
  2347. // 3. When has arguments and in debug mode. So that frame display be there along with frame object register.
  2348. if (top->GetCallsEval() ||
  2349. pnode->sxFnc.nestedCount != 0
  2350. || (top->GetHasArguments()
  2351. && (pnode->sxFnc.pnodeArgs != nullptr)
  2352. && byteCodeGenerator->IsInDebugMode()))
  2353. {
  2354. byteCodeGenerator->SetNeedEnvRegister(); // This to ensure that Env should be there when the FrameDisplay register is there.
  2355. byteCodeGenerator->AssignFrameDisplayRegister();
  2356. if (top->GetIsEventHandler())
  2357. {
  2358. byteCodeGenerator->AssignThisRegister();
  2359. }
  2360. }
  2361. }
  2362. if (top->GetHasArguments())
  2363. {
  2364. Symbol *argSym = top->GetArgumentsSymbol();
  2365. Assert(argSym);
  2366. if (argSym)
  2367. {
  2368. Assert(top->bodyScope->GetScopeSlotCount() == 0);
  2369. Assert(top->sameNameArgsPlaceHolderSlotCount == 0);
  2370. byteCodeGenerator->AssignRegister(argSym);
  2371. uint i = 0;
  2372. auto setArgScopeSlot = [&](ParseNode *pnodeArg)
  2373. {
  2374. if (pnodeArg->IsVarLetOrConst())
  2375. {
  2376. Symbol* sym = pnodeArg->sxVar.sym;
  2377. if (sym->GetScopeSlot() != Js::Constants::NoProperty)
  2378. {
  2379. top->sameNameArgsPlaceHolderSlotCount++; // Same name args appeared before
  2380. }
  2381. sym->SetScopeSlot(i);
  2382. i++;
  2383. }
  2384. };
  2385. // We don't need to process the rest parameter here because it may not need a scope slot.
  2386. if (ByteCodeGenerator::NeedScopeObjectForArguments(top, pnode))
  2387. {
  2388. MapFormalsWithoutRest(pnode, setArgScopeSlot);
  2389. MapFormalsFromPattern(pnode, setArgScopeSlot);
  2390. }
  2391. top->paramScope->SetScopeSlotCount(i);
  2392. Assert(top->GetHasHeapArguments());
  2393. if (ByteCodeGenerator::NeedScopeObjectForArguments(top, pnode)
  2394. && pnode->sxFnc.IsSimpleParameterList())
  2395. {
  2396. top->byteCodeFunction->SetHasImplicitArgIns(false);
  2397. }
  2398. }
  2399. }
  2400. }
  2401. else
  2402. {
  2403. Assert(top->IsGlobalFunction());
  2404. // eval is called in strict mode
  2405. bool newScopeForEval = (top->byteCodeFunction->GetIsStrictMode() && (byteCodeGenerator->GetFlags() & fscrEval));
  2406. if (newScopeForEval)
  2407. {
  2408. byteCodeGenerator->SetNeedEnvRegister();
  2409. byteCodeGenerator->AssignFrameObjRegister();
  2410. byteCodeGenerator->AssignFrameDisplayRegister();
  2411. }
  2412. }
  2413. Assert(!funcExprWithName || sym);
  2414. if (funcExprWithName)
  2415. {
  2416. Assert(top->funcExprScope);
  2417. // If the func expr may be accessed via eval, force the func expr scope into an object.
  2418. if (top->GetCallsEval() || top->GetChildCallsEval())
  2419. {
  2420. top->funcExprScope->SetIsObject();
  2421. }
  2422. if (top->funcExprScope->GetIsObject())
  2423. {
  2424. top->funcExprScope->SetLocation(byteCodeGenerator->NextVarRegister());
  2425. }
  2426. }
  2427. }
  2428. byteCodeGenerator->EndBindFunction(funcExprWithName);
  2429. // If the "child" is the global function, we're done.
  2430. if (top->IsGlobalFunction())
  2431. {
  2432. return top;
  2433. }
  2434. FuncInfo* const parentFunc = byteCodeGenerator->TopFuncInfo();
  2435. Js::FunctionBody * parentFunctionBody = parentFunc->byteCodeFunction->GetFunctionBody();
  2436. Assert(parentFunctionBody != nullptr);
  2437. bool const hasAnyDeferredChild = top->HasDeferredChild() || top->IsDeferred();
  2438. bool setHasNonLocalReference = parentFunctionBody->HasAllNonLocalReferenced();
  2439. // If we have any deferred child, we need to instantiate the fake global block scope if it is not empty
  2440. if (parentFunc->IsGlobalFunction())
  2441. {
  2442. if (hasAnyDeferredChild && byteCodeGenerator->IsEvalWithBlockScopingNoParentScopeInfo())
  2443. {
  2444. Scope * globalEvalBlockScope = parentFunc->GetGlobalEvalBlockScope();
  2445. if (globalEvalBlockScope->Count() != 0 || parentFunc->isThisLexicallyCaptured)
  2446. {
  2447. // We must instantiate the eval block scope if we have any deferred child
  2448. // and force all symbol to have non local reference so it will be captured
  2449. // by the scope.
  2450. globalEvalBlockScope->SetMustInstantiate(true);
  2451. globalEvalBlockScope->ForceAllSymbolNonLocalReference(byteCodeGenerator);
  2452. parentFunc->SetHasDeferredChild();
  2453. }
  2454. }
  2455. }
  2456. else
  2457. {
  2458. if (setHasNonLocalReference)
  2459. {
  2460. // All locals are already marked as non-locals-referenced. Mark the parent as well.
  2461. if (parentFunctionBody->HasSetIsObject())
  2462. {
  2463. // Updated the current function, as per the previous stored info.
  2464. parentFunc->GetBodyScope()->SetIsObject();
  2465. parentFunc->GetParamScope()->SetIsObject();
  2466. }
  2467. }
  2468. // Propagate "hasDeferredChild" attribute back to parent.
  2469. if (hasAnyDeferredChild)
  2470. {
  2471. Assert(CONFIG_FLAG(DeferNested));
  2472. parentFunc->SetHasDeferredChild();
  2473. // Anything in parent may have non-local reference from deferredChild.
  2474. setHasNonLocalReference = true;
  2475. parentFunctionBody->SetAllNonLocalReferenced(true);
  2476. // If a deferred child has with, parent scopes may contain symbols called inside the with.
  2477. // Current implementation needs the symScope isObject.
  2478. if (top->ChildHasWith() || pnode->sxFnc.HasWithStmt())
  2479. {
  2480. parentFunc->SetChildHasWith();
  2481. parentFunc->GetBodyScope()->SetIsObject();
  2482. parentFunc->GetParamScope()->SetIsObject();
  2483. // Record this for future use in the no-refresh debugging.
  2484. parentFunctionBody->SetHasSetIsObject(true);
  2485. }
  2486. }
  2487. // Propagate HasMaybeEscapedNestedFunc
  2488. if (!byteCodeGenerator->CanStackNestedFunc(top, false) ||
  2489. byteCodeGenerator->NeedObjectAsFunctionScope(top, pnode))
  2490. {
  2491. parentFunc->SetHasMaybeEscapedNestedFunc(DebugOnly(L"Child"));
  2492. }
  2493. }
  2494. if (top->GetCallsEval() || top->GetChildCallsEval())
  2495. {
  2496. parentFunc->SetChildCallsEval(true);
  2497. ParseNode *currentBlock = byteCodeGenerator->GetCurrentBlock();
  2498. if (currentBlock)
  2499. {
  2500. Assert(currentBlock->nop == knopBlock);
  2501. currentBlock->sxBlock.SetChildCallsEval(true);
  2502. }
  2503. parentFunc->SetHasHeapArguments(true);
  2504. setHasNonLocalReference = true;
  2505. parentFunctionBody->SetAllNonLocalReferenced(true);
  2506. Scope * const funcExprScope = top->funcExprScope;
  2507. if (funcExprScope)
  2508. {
  2509. // If we have the body scope as an object, the outer function expression scope also needs to be an object to propagate the name.
  2510. funcExprScope->SetIsObject();
  2511. }
  2512. if (parentFunc->inArgsCount == 1)
  2513. {
  2514. // If no formals to function, no need to create the propertyid array
  2515. byteCodeGenerator->AssignNullConstRegister();
  2516. }
  2517. }
  2518. if (setHasNonLocalReference && !parentFunctionBody->HasDoneAllNonLocalReferenced())
  2519. {
  2520. parentFunc->GetBodyScope()->ForceAllSymbolNonLocalReference(byteCodeGenerator);
  2521. if (!parentFunc->IsGlobalFunction())
  2522. {
  2523. parentFunc->GetParamScope()->ForceAllSymbolNonLocalReference(byteCodeGenerator);
  2524. }
  2525. parentFunctionBody->SetHasDoneAllNonLocalReferenced(true);
  2526. }
  2527. if (top->HasSuperReference())
  2528. {
  2529. top->AssignSuperRegister();
  2530. }
  2531. if (top->HasDirectSuper())
  2532. {
  2533. top->AssignSuperCtorRegister();
  2534. }
  2535. if (top->IsClassConstructor())
  2536. {
  2537. if (top->IsBaseClassConstructor())
  2538. {
  2539. // Base class constructor may not explicitly reference new.target but we always need to have it in order to construct the 'this' object.
  2540. top->AssignNewTargetRegister();
  2541. // Also must have a register to slot the 'this' object into.
  2542. top->AssignThisRegister();
  2543. }
  2544. else
  2545. {
  2546. // Derived class constructors need to check undefined against explicit return statements.
  2547. top->AssignUndefinedConstRegister();
  2548. top->AssignNewTargetRegister();
  2549. if (top->GetCallsEval() || top->GetChildCallsEval())
  2550. {
  2551. top->AssignThisRegister();
  2552. top->SetIsThisLexicallyCaptured();
  2553. top->SetIsNewTargetLexicallyCaptured();
  2554. top->SetIsSuperLexicallyCaptured();
  2555. top->SetIsSuperCtorLexicallyCaptured();
  2556. top->SetHasLocalInClosure(true);
  2557. top->SetHasClosureReference(true);
  2558. top->SetHasCapturedThis();
  2559. }
  2560. }
  2561. }
  2562. AssignFuncSymRegister(pnode, byteCodeGenerator, top);
  2563. return top;
  2564. }
  2565. void MarkInit(ParseNode* pnode)
  2566. {
  2567. if (pnode->nop == knopList)
  2568. {
  2569. do
  2570. {
  2571. MarkInit(pnode->sxBin.pnode1);
  2572. pnode = pnode->sxBin.pnode2;
  2573. }
  2574. while (pnode->nop == knopList);
  2575. MarkInit(pnode);
  2576. }
  2577. else
  2578. {
  2579. Symbol *sym = nullptr;
  2580. ParseNode *pnodeInit = nullptr;
  2581. if (pnode->nop == knopVarDecl)
  2582. {
  2583. sym = pnode->sxVar.sym;
  2584. pnodeInit = pnode->sxVar.pnodeInit;
  2585. }
  2586. else if (pnode->nop == knopAsg && pnode->sxBin.pnode1->nop == knopName)
  2587. {
  2588. sym = pnode->sxBin.pnode1->sxPid.sym;
  2589. pnodeInit = pnode->sxBin.pnode2;
  2590. }
  2591. if (sym && !sym->GetIsUsed() && pnodeInit)
  2592. {
  2593. sym->SetHasInit(true);
  2594. if (sym->HasVisitedCapturingFunc())
  2595. {
  2596. sym->SetHasNonCommittedReference(false);
  2597. }
  2598. }
  2599. }
  2600. }
  2601. void AddFunctionsToScope(ParseNodePtr scope, ByteCodeGenerator * byteCodeGenerator)
  2602. {
  2603. VisitFncDecls(scope, [byteCodeGenerator](ParseNode *fn)
  2604. {
  2605. ParseNode *pnodeName = fn->sxFnc.pnodeName;
  2606. if (pnodeName && pnodeName->nop == knopVarDecl && fn->sxFnc.IsDeclaration())
  2607. {
  2608. const wchar_t *fnName = pnodeName->sxVar.pid->Psz();
  2609. if (byteCodeGenerator->Trace())
  2610. {
  2611. Output::Print(L"current context has declared function %s\n", fnName);
  2612. }
  2613. // In ES6, functions are scoped to the block, which will be the current scope.
  2614. // Pre-ES6, function declarations are scoped to the function body, so get that scope.
  2615. Symbol *sym;
  2616. if (!byteCodeGenerator->GetCurrentScope()->IsGlobalEvalBlockScope())
  2617. {
  2618. sym = byteCodeGenerator->AddSymbolToScope(byteCodeGenerator->GetCurrentScope(), fnName, pnodeName->sxVar.pid->Cch(), pnodeName, STFunction);
  2619. }
  2620. else
  2621. {
  2622. sym = byteCodeGenerator->AddSymbolToFunctionScope(fnName, pnodeName->sxVar.pid->Cch(), pnodeName, STFunction);
  2623. }
  2624. pnodeName->sxVar.sym = sym;
  2625. if (sym->GetIsGlobal())
  2626. {
  2627. FuncInfo* func = byteCodeGenerator->TopFuncInfo();
  2628. func->SetHasGlobalRef(true);
  2629. }
  2630. if (byteCodeGenerator->GetScriptContext()->GetConfig()->IsBlockScopeEnabled()
  2631. && sym->GetScope() != sym->GetScope()->GetFunc()->GetBodyScope()
  2632. && sym->GetScope() != sym->GetScope()->GetFunc()->GetParamScope())
  2633. {
  2634. sym->SetIsBlockVar(true);
  2635. }
  2636. }
  2637. });
  2638. }
  2639. template <class PrefixFn, class PostfixFn>
  2640. void VisitNestedScopes(ParseNode* pnodeScopeList, ParseNode* pnodeParent, ByteCodeGenerator* byteCodeGenerator,
  2641. PrefixFn prefix, PostfixFn postfix, uint *pIndex)
  2642. {
  2643. // Visit all scopes nested in this scope before visiting this function's statements. This way we have all the
  2644. // attributes of all the inner functions before we assign registers within this function.
  2645. // All the attributes we need to propagate downward should already be recorded by the parser.
  2646. // - call to "eval()"
  2647. // - nested in "with"
  2648. Js::ParseableFunctionInfo* parentFunc = pnodeParent->sxFnc.funcInfo->byteCodeFunction;
  2649. ParseNode* pnodeScope;
  2650. uint i = 0;
  2651. // Cache to restore it back once we come out of current function.
  2652. Js::FunctionBody * pLastReuseFunc = byteCodeGenerator->pCurrentFunction;
  2653. for (pnodeScope = pnodeScopeList; pnodeScope;)
  2654. {
  2655. switch (pnodeScope->nop)
  2656. {
  2657. case knopFncDecl:
  2658. if (pLastReuseFunc)
  2659. {
  2660. if (!byteCodeGenerator->IsInNonDebugMode())
  2661. {
  2662. // Here we are trying to match the inner sub-tree as well with already created inner function.
  2663. if ((pLastReuseFunc->GetIsGlobalFunc() && parentFunc->GetIsGlobalFunc())
  2664. || (!pLastReuseFunc->GetIsGlobalFunc() && !parentFunc->GetIsGlobalFunc()))
  2665. {
  2666. Assert(pLastReuseFunc->StartInDocument() == pnodeParent->ichMin);
  2667. Assert(pLastReuseFunc->LengthInChars() == pnodeParent->LengthInCodepoints());
  2668. Assert(pLastReuseFunc->GetNestedCount() == parentFunc->GetNestedCount());
  2669. // If the current function is not parsed yet, its function body is not generated yet.
  2670. // Reset pCurrentFunction to null so that it will not be able re-use anything.
  2671. Js::FunctionProxy* proxy = pLastReuseFunc->GetNestedFunc((*pIndex));
  2672. if (proxy && proxy->IsFunctionBody())
  2673. {
  2674. byteCodeGenerator->pCurrentFunction = proxy->GetFunctionBody();
  2675. }
  2676. else
  2677. {
  2678. byteCodeGenerator->pCurrentFunction = nullptr;
  2679. }
  2680. }
  2681. }
  2682. else if (!parentFunc->GetIsGlobalFunc())
  2683. {
  2684. // In the deferred parsing mode, we will be reusing the only one function (which is asked when on ::Begin) all inner function will be created.
  2685. byteCodeGenerator->pCurrentFunction = nullptr;
  2686. }
  2687. }
  2688. PreVisitFunction(pnodeScope, byteCodeGenerator);
  2689. pnodeParent->sxFnc.funcInfo->OnStartVisitFunction(pnodeScope);
  2690. if (pnodeScope->sxFnc.pnodeBody)
  2691. {
  2692. if (!byteCodeGenerator->IsInNonDebugMode() && pLastReuseFunc != nullptr && byteCodeGenerator->pCurrentFunction == nullptr)
  2693. {
  2694. // Patch current non-parsed function's FunctionBodyImpl with the new generated function body.
  2695. // So that the function object (pointing to the old function body) can able to get to the new one.
  2696. Js::FunctionProxy* proxy = pLastReuseFunc->GetNestedFunc((*pIndex));
  2697. if (proxy && !proxy->IsFunctionBody())
  2698. {
  2699. proxy->UpdateFunctionBodyImpl(pnodeScope->sxFnc.funcInfo->byteCodeFunction->GetFunctionBody());
  2700. }
  2701. }
  2702. BeginVisitBlock(pnodeScope->sxFnc.pnodeScopes, byteCodeGenerator);
  2703. i = 0;
  2704. ParseNodePtr containerScope = pnodeScope->sxFnc.pnodeScopes;
  2705. VisitNestedScopes(containerScope, pnodeScope, byteCodeGenerator, prefix, postfix, &i);
  2706. MapFormals(pnodeScope, [&](ParseNode *argNode) { Visit(argNode, byteCodeGenerator, prefix, postfix); });
  2707. if (!pnodeScope->sxFnc.IsSimpleParameterList())
  2708. {
  2709. byteCodeGenerator->AssignUndefinedConstRegister();
  2710. }
  2711. BeginVisitBlock(pnodeScope->sxFnc.pnodeBodyScope, byteCodeGenerator);
  2712. ParseNode* pnode = pnodeScope->sxFnc.pnodeBody;
  2713. while (pnode->nop == knopList)
  2714. {
  2715. // Check to see whether initializations of locals to "undef" can be skipped.
  2716. // The logic to do this is cheap - omit the init if we see an init with a value
  2717. // on the RHS at the top statement level (i.e., not inside a block, try, loop, etc.)
  2718. // before we see a use. The motivation is to help identify single-def locals in the BE.
  2719. // Note that this can't be done for globals.
  2720. byteCodeGenerator->SetCurrentTopStatement(pnode->sxBin.pnode1);
  2721. Visit(pnode->sxBin.pnode1, byteCodeGenerator, prefix, postfix);
  2722. if (!pnodeScope->sxFnc.funcInfo->GetCallsEval() &&
  2723. !pnodeScope->sxFnc.funcInfo->GetChildCallsEval() &&
  2724. // So that it will not be marked as init thus it will be added to the diagnostics symbols container.
  2725. !(byteCodeGenerator->ShouldTrackDebuggerMetadata()))
  2726. {
  2727. MarkInit(pnode->sxBin.pnode1);
  2728. }
  2729. pnode = pnode->sxBin.pnode2;
  2730. }
  2731. byteCodeGenerator->SetCurrentTopStatement(pnode);
  2732. Visit(pnode, byteCodeGenerator, prefix, postfix);
  2733. EndVisitBlock(pnodeScope->sxFnc.pnodeBodyScope, byteCodeGenerator);
  2734. EndVisitBlock(pnodeScope->sxFnc.pnodeScopes, byteCodeGenerator);
  2735. }
  2736. else if (pnodeScope->sxFnc.nestedCount)
  2737. {
  2738. // The nested function is deferred but has its own nested functions.
  2739. // Make sure we at least zero-initialize its array in case, for instance, we get cloned
  2740. // before the function is called and the array filled in.
  2741. #ifdef RECYCLER_WRITE_BARRIER
  2742. WriteBarrierPtr<Js::FunctionProxy>::ClearArray(pnodeScope->sxFnc.funcInfo->byteCodeFunction->GetNestedFuncArray(), pnodeScope->sxFnc.nestedCount);
  2743. #else
  2744. memset(pnodeScope->sxFnc.funcInfo->byteCodeFunction->GetNestedFuncArray(), 0, pnodeScope->sxFnc.nestedCount * sizeof(Js::FunctionBody*));
  2745. #endif
  2746. }
  2747. pnodeScope->sxFnc.nestedIndex = *pIndex;
  2748. parentFunc->SetNestedFunc(pnodeScope->sxFnc.funcInfo->byteCodeFunction, (*pIndex)++, byteCodeGenerator->GetFlags());
  2749. Assert(parentFunc);
  2750. pnodeParent->sxFnc.funcInfo->OnEndVisitFunction(pnodeScope);
  2751. PostVisitFunction(pnodeScope, byteCodeGenerator);
  2752. // Merge parameter and body scopes, unless we are deferring the function.
  2753. // If we are deferring the function, we will need both scopes to do the proper binding when
  2754. // the function is undeferred. After the function is undeferred, it is safe to merge the scopes.
  2755. if (pnodeScope->sxFnc.funcInfo->paramScope != nullptr && pnodeScope->sxFnc.pnodeBody != nullptr)
  2756. {
  2757. Scope::MergeParamAndBodyScopes(pnodeScope, byteCodeGenerator);
  2758. }
  2759. pnodeScope = pnodeScope->sxFnc.pnodeNext;
  2760. byteCodeGenerator->pCurrentFunction = pLastReuseFunc;
  2761. break;
  2762. case knopBlock:
  2763. PreVisitBlock(pnodeScope, byteCodeGenerator);
  2764. pnodeParent->sxFnc.funcInfo->OnStartVisitScope(pnodeScope->sxBlock.scope);
  2765. VisitNestedScopes(pnodeScope->sxBlock.pnodeScopes, pnodeParent, byteCodeGenerator, prefix, postfix, pIndex);
  2766. pnodeParent->sxFnc.funcInfo->OnEndVisitScope(pnodeScope->sxBlock.scope);
  2767. PostVisitBlock(pnodeScope, byteCodeGenerator);
  2768. pnodeScope = pnodeScope->sxBlock.pnodeNext;
  2769. break;
  2770. case knopCatch:
  2771. PreVisitCatch(pnodeScope, byteCodeGenerator);
  2772. Visit(pnodeScope->sxCatch.pnodeParam, byteCodeGenerator, prefix, postfix);
  2773. if (pnodeScope->sxCatch.pnodeParam->nop == knopParamPattern)
  2774. {
  2775. if (pnodeScope->sxCatch.pnodeParam->sxParamPattern.location == Js::Constants::NoRegister)
  2776. {
  2777. pnodeScope->sxCatch.pnodeParam->sxParamPattern.location = byteCodeGenerator->NextVarRegister();
  2778. }
  2779. }
  2780. pnodeParent->sxFnc.funcInfo->OnStartVisitScope(pnodeScope->sxCatch.scope);
  2781. VisitNestedScopes(pnodeScope->sxCatch.pnodeScopes, pnodeParent, byteCodeGenerator, prefix, postfix, pIndex);
  2782. pnodeParent->sxFnc.funcInfo->OnEndVisitScope(pnodeScope->sxCatch.scope);
  2783. PostVisitCatch(pnodeScope, byteCodeGenerator);
  2784. pnodeScope = pnodeScope->sxCatch.pnodeNext;
  2785. break;
  2786. case knopWith:
  2787. PreVisitWith(pnodeScope, byteCodeGenerator);
  2788. pnodeParent->sxFnc.funcInfo->OnStartVisitScope(pnodeScope->sxWith.scope);
  2789. VisitNestedScopes(pnodeScope->sxWith.pnodeScopes, pnodeParent, byteCodeGenerator, prefix, postfix, pIndex);
  2790. pnodeParent->sxFnc.funcInfo->OnEndVisitScope(pnodeScope->sxWith.scope);
  2791. PostVisitWith(pnodeScope, byteCodeGenerator);
  2792. pnodeScope = pnodeScope->sxWith.pnodeNext;
  2793. break;
  2794. default:
  2795. AssertMsg(false, "Unexpected opcode in tree of scopes");
  2796. return;
  2797. }
  2798. }
  2799. }
  2800. void PreVisitBlock(ParseNode *pnodeBlock, ByteCodeGenerator *byteCodeGenerator)
  2801. {
  2802. if (!pnodeBlock->sxBlock.scope &&
  2803. !pnodeBlock->sxBlock.HasBlockScopedContent() &&
  2804. !pnodeBlock->sxBlock.GetCallsEval())
  2805. {
  2806. // Do nothing here if the block doesn't declare anything or call eval (which may declare something).
  2807. return;
  2808. }
  2809. bool isGlobalEvalBlockScope = false;
  2810. FuncInfo *func = byteCodeGenerator->TopFuncInfo();
  2811. if (func->IsGlobalFunction() &&
  2812. func->root->sxFnc.pnodeScopes == pnodeBlock &&
  2813. byteCodeGenerator->IsEvalWithBlockScopingNoParentScopeInfo())
  2814. {
  2815. isGlobalEvalBlockScope = true;
  2816. }
  2817. Assert(!byteCodeGenerator->UseParserBindings() ||
  2818. !pnodeBlock->sxBlock.scope ||
  2819. isGlobalEvalBlockScope == (pnodeBlock->sxBlock.scope->GetScopeType() == ScopeType_GlobalEvalBlock));
  2820. ArenaAllocator *alloc = byteCodeGenerator->GetAllocator();
  2821. Scope *scope;
  2822. if ((pnodeBlock->sxBlock.blockType == PnodeBlockType::Global && !byteCodeGenerator->IsEvalWithBlockScopingNoParentScopeInfo()) || pnodeBlock->sxBlock.blockType == PnodeBlockType::Function)
  2823. {
  2824. scope = byteCodeGenerator->GetCurrentScope();
  2825. if (pnodeBlock->sxBlock.blockType == PnodeBlockType::Function)
  2826. {
  2827. AnalysisAssert(pnodeBlock->sxBlock.scope);
  2828. if (pnodeBlock->sxBlock.scope->GetScopeType() == ScopeType_Parameter
  2829. && scope->GetScopeType() == ScopeType_FunctionBody)
  2830. {
  2831. scope = scope->GetEnclosingScope();
  2832. }
  2833. }
  2834. pnodeBlock->sxBlock.scope = scope;
  2835. }
  2836. else if (!(pnodeBlock->grfpn & fpnSyntheticNode) || isGlobalEvalBlockScope)
  2837. {
  2838. Assert(byteCodeGenerator->GetScriptContext()->GetConfig()->IsBlockScopeEnabled());
  2839. scope = pnodeBlock->sxBlock.scope;
  2840. if (!scope || !byteCodeGenerator->UseParserBindings())
  2841. {
  2842. scope = Anew(alloc, Scope, alloc,
  2843. isGlobalEvalBlockScope? ScopeType_GlobalEvalBlock : ScopeType_Block, true);
  2844. pnodeBlock->sxBlock.scope = scope;
  2845. }
  2846. scope->SetFunc(byteCodeGenerator->TopFuncInfo());
  2847. // For now, prevent block scope from being merged with enclosing function scope.
  2848. // Consider optimizing this.
  2849. scope->SetCanMerge(false);
  2850. if (isGlobalEvalBlockScope)
  2851. {
  2852. scope->SetIsObject();
  2853. }
  2854. byteCodeGenerator->PushScope(scope);
  2855. byteCodeGenerator->PushBlock(pnodeBlock);
  2856. }
  2857. else
  2858. {
  2859. return;
  2860. }
  2861. Assert(scope && scope == pnodeBlock->sxBlock.scope);
  2862. bool isGlobalScope = (scope->GetEnclosingScope() == nullptr);
  2863. Assert(!isGlobalScope || (pnodeBlock->grfpn & fpnSyntheticNode));
  2864. // If it is the global eval block scope, we don't what function decl to be assigned in the block scope.
  2865. // They should already declared in the global function's scope.
  2866. if (!isGlobalEvalBlockScope && !isGlobalScope)
  2867. {
  2868. AddFunctionsToScope(pnodeBlock->sxBlock.pnodeScopes, byteCodeGenerator);
  2869. }
  2870. // We can skip this check by not creating the GlobalEvalBlock above and in Parser::Parse for console eval but that seems to break couple of places
  2871. // as we heavily depend on BlockHasOwnScope function. Once we clean up the creation of GlobalEvalBlock for evals we can clean this as well.
  2872. if (byteCodeGenerator->IsConsoleScopeEval() && isGlobalEvalBlockScope && !isGlobalScope)
  2873. {
  2874. AssertMsg(scope->GetEnclosingScope()->GetScopeType() == ScopeType_Global, "Additional scope between Global and GlobalEvalBlock?");
  2875. scope = scope->GetEnclosingScope();
  2876. isGlobalScope = true;
  2877. }
  2878. auto addSymbolToScope = [scope, byteCodeGenerator, isGlobalScope](ParseNode *pnode)
  2879. {
  2880. Symbol *sym = byteCodeGenerator->AddSymbolToScope(scope, reinterpret_cast<const wchar_t*>(pnode->sxVar.pid->Psz()), pnode->sxVar.pid->Cch(), pnode, STVariable);
  2881. #if DBG_DUMP
  2882. if (sym->GetSymbolType() == STVariable && byteCodeGenerator->Trace())
  2883. {
  2884. Output::Print(L"current context has declared %s %s of type %s\n",
  2885. sym->GetDecl()->nop == knopLetDecl ? L"let" : L"const",
  2886. pnode->sxVar.pid->Psz(),
  2887. sym->GetSymbolTypeName());
  2888. }
  2889. #endif
  2890. sym->SetIsGlobal(isGlobalScope);
  2891. sym->SetIsBlockVar(true);
  2892. sym->SetNeedDeclaration(true);
  2893. pnode->sxVar.sym = sym;
  2894. };
  2895. byteCodeGenerator->IterateBlockScopedVariables(pnodeBlock, addSymbolToScope);
  2896. }
  2897. void PostVisitBlock(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  2898. {
  2899. if (!BlockHasOwnScope(pnode, byteCodeGenerator))
  2900. {
  2901. return;
  2902. }
  2903. if (pnode->sxBlock.GetCallsEval() || pnode->sxBlock.GetChildCallsEval() || (byteCodeGenerator->GetFlags() & (fscrEval | fscrImplicitThis | fscrImplicitParents)))
  2904. {
  2905. Scope *scope = pnode->sxBlock.scope;
  2906. bool scopeIsEmpty = scope->IsEmpty();
  2907. scope->SetIsObject();
  2908. scope->SetCapturesAll(true);
  2909. scope->SetMustInstantiate(!scopeIsEmpty);
  2910. }
  2911. byteCodeGenerator->PopScope();
  2912. byteCodeGenerator->PopBlock();
  2913. ParseNode *currentBlock = byteCodeGenerator->GetCurrentBlock();
  2914. if (currentBlock && (pnode->sxBlock.GetCallsEval() || pnode->sxBlock.GetChildCallsEval()))
  2915. {
  2916. currentBlock->sxBlock.SetChildCallsEval(true);
  2917. }
  2918. }
  2919. void PreVisitCatch(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  2920. {
  2921. // Push the catch scope and add the catch expression to it.
  2922. byteCodeGenerator->StartBindCatch(pnode);
  2923. if (pnode->sxCatch.pnodeParam->nop == knopParamPattern)
  2924. {
  2925. Parser::MapBindIdentifier(pnode->sxCatch.pnodeParam->sxParamPattern.pnode1, [&](ParseNodePtr item)
  2926. {
  2927. Symbol *sym = item->sxVar.sym;
  2928. if (!byteCodeGenerator->UseParserBindings())
  2929. {
  2930. sym = byteCodeGenerator->AddSymbolToScope(pnode->sxCatch.scope, reinterpret_cast<const wchar_t*>(item->sxVar.pid->Psz()), item->sxVar.pid->Cch(), item, STVariable);
  2931. item->sxVar.sym = sym;
  2932. }
  2933. #if DBG_DUMP
  2934. if (byteCodeGenerator->Trace())
  2935. {
  2936. Output::Print(L"current context has declared catch var %s of type %s\n",
  2937. item->sxVar.pid->Psz(), sym->GetSymbolTypeName());
  2938. }
  2939. #endif
  2940. });
  2941. }
  2942. else
  2943. {
  2944. Symbol *sym;
  2945. if (!byteCodeGenerator->UseParserBindings())
  2946. {
  2947. sym = byteCodeGenerator->AddSymbolToScope(pnode->sxCatch.scope, reinterpret_cast<const wchar_t*>(pnode->sxCatch.pnodeParam->sxPid.pid->Psz()), pnode->sxCatch.pnodeParam->sxPid.pid->Cch(), pnode->sxCatch.pnodeParam, STVariable);
  2948. }
  2949. else
  2950. {
  2951. sym = *pnode->sxCatch.pnodeParam->sxPid.symRef;
  2952. }
  2953. Assert(sym->GetScope() == pnode->sxCatch.scope);
  2954. #if DBG_DUMP
  2955. if (byteCodeGenerator->Trace())
  2956. {
  2957. Output::Print(L"current context has declared catch var %s of type %s\n",
  2958. pnode->sxCatch.pnodeParam->sxPid.pid->Psz(), sym->GetSymbolTypeName());
  2959. }
  2960. #endif
  2961. sym->SetIsCatch(true);
  2962. pnode->sxCatch.pnodeParam->sxPid.sym = sym;
  2963. }
  2964. // This call will actually add the nested function symbols to the enclosing function scope (which is what we want).
  2965. AddFunctionsToScope(pnode->sxCatch.pnodeScopes, byteCodeGenerator);
  2966. }
  2967. void PostVisitCatch(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  2968. {
  2969. byteCodeGenerator->EndBindCatch();
  2970. }
  2971. void PreVisitWith(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  2972. {
  2973. ArenaAllocator *alloc = byteCodeGenerator->GetAllocator();
  2974. Scope *scope = Anew(alloc, Scope, alloc, ScopeType_With);
  2975. scope->SetFunc(byteCodeGenerator->TopFuncInfo());
  2976. scope->SetIsDynamic(true);
  2977. pnode->sxWith.scope = scope;
  2978. byteCodeGenerator->PushScope(scope);
  2979. }
  2980. void PostVisitWith(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  2981. {
  2982. byteCodeGenerator->PopScope();
  2983. }
  2984. void BindFuncSymbol(ParseNode *pnodeFnc, ByteCodeGenerator *byteCodeGenerator)
  2985. {
  2986. if (pnodeFnc->sxFnc.pnodeName)
  2987. {
  2988. Assert(pnodeFnc->sxFnc.pnodeName->nop == knopVarDecl);
  2989. Symbol *sym = pnodeFnc->sxFnc.pnodeName->sxVar.sym;
  2990. FuncInfo* func = byteCodeGenerator->TopFuncInfo();
  2991. if (sym == nullptr || sym->GetIsGlobal())
  2992. {
  2993. func->SetHasGlobalRef(true);
  2994. }
  2995. }
  2996. }
  2997. bool IsMathLibraryId(Js::PropertyId propertyId)
  2998. {
  2999. return (propertyId >= Js::PropertyIds::abs) && (propertyId <= Js::PropertyIds::fround);
  3000. }
  3001. bool IsLibraryFunction(ParseNode* expr, Js::ScriptContext* scriptContext)
  3002. {
  3003. if (expr && expr->nop == knopDot)
  3004. {
  3005. ParseNode* lhs = expr->sxBin.pnode1;
  3006. ParseNode* rhs = expr->sxBin.pnode2;
  3007. if ((lhs != nullptr) && (rhs != nullptr) && (lhs->nop == knopName) && (rhs->nop == knopName))
  3008. {
  3009. Symbol* lsym = lhs->sxPid.sym;
  3010. if ((lsym == nullptr || lsym->GetIsGlobal()) && lhs->sxPid.PropertyIdFromNameNode() == Js::PropertyIds::Math)
  3011. {
  3012. return IsMathLibraryId(rhs->sxPid.PropertyIdFromNameNode());
  3013. }
  3014. }
  3015. }
  3016. return false;
  3017. }
  3018. struct SymCheck
  3019. {
  3020. static const int kMaxInvertedSyms = 8;
  3021. Symbol* syms[kMaxInvertedSyms];
  3022. Symbol* permittedSym;
  3023. int symCount;
  3024. bool result;
  3025. bool cond;
  3026. bool AddSymbol(Symbol* sym)
  3027. {
  3028. if (symCount < kMaxInvertedSyms)
  3029. {
  3030. syms[symCount++] = sym;
  3031. return true;
  3032. }
  3033. else
  3034. {
  3035. return false;
  3036. }
  3037. }
  3038. bool MatchSymbol(Symbol* sym)
  3039. {
  3040. if (sym != permittedSym)
  3041. {
  3042. for (int i = 0; i < symCount; i++)
  3043. {
  3044. if (sym == syms[i])
  3045. {
  3046. return true;
  3047. }
  3048. }
  3049. }
  3050. return false;
  3051. }
  3052. void Init()
  3053. {
  3054. symCount = 0;
  3055. result = true;
  3056. }
  3057. };
  3058. void CheckInvertableExpr(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, SymCheck* symCheck)
  3059. {
  3060. if (symCheck->result)
  3061. {
  3062. switch (pnode->nop)
  3063. {
  3064. case knopName:
  3065. if (symCheck->MatchSymbol(pnode->sxPid.sym))
  3066. {
  3067. symCheck->result = false;
  3068. }
  3069. break;
  3070. case knopCall:
  3071. {
  3072. ParseNode* callTarget = pnode->sxBin.pnode1;
  3073. if (callTarget != nullptr)
  3074. {
  3075. if (callTarget->nop == knopName)
  3076. {
  3077. Symbol* sym = callTarget->sxPid.sym;
  3078. if (sym && sym->SingleDef())
  3079. {
  3080. ParseNode* decl = sym->GetDecl();
  3081. if (decl == nullptr ||
  3082. decl->nop != knopVarDecl ||
  3083. !IsLibraryFunction(decl->sxVar.pnodeInit, byteCodeGenerator->GetScriptContext()))
  3084. {
  3085. symCheck->result = false;
  3086. }
  3087. }
  3088. else
  3089. {
  3090. symCheck->result = false;
  3091. }
  3092. }
  3093. else if (callTarget->nop == knopDot)
  3094. {
  3095. if (!IsLibraryFunction(callTarget, byteCodeGenerator->GetScriptContext()))
  3096. {
  3097. symCheck->result = false;
  3098. }
  3099. }
  3100. }
  3101. else
  3102. {
  3103. symCheck->result = false;
  3104. }
  3105. break;
  3106. }
  3107. case knopDot:
  3108. if (!IsLibraryFunction(pnode, byteCodeGenerator->GetScriptContext()))
  3109. {
  3110. symCheck->result = false;
  3111. }
  3112. break;
  3113. case knopTrue:
  3114. case knopFalse:
  3115. case knopAdd:
  3116. case knopSub:
  3117. case knopDiv:
  3118. case knopMul:
  3119. case knopExpo:
  3120. case knopMod:
  3121. case knopNeg:
  3122. case knopInt:
  3123. case knopFlt:
  3124. case knopLt:
  3125. case knopGt:
  3126. case knopLe:
  3127. case knopGe:
  3128. case knopEq:
  3129. case knopNe:
  3130. break;
  3131. default:
  3132. symCheck->result = false;
  3133. break;
  3134. }
  3135. }
  3136. }
  3137. bool InvertableExpr(SymCheck* symCheck, ParseNode* expr, ByteCodeGenerator* byteCodeGenerator)
  3138. {
  3139. symCheck->result = true;
  3140. symCheck->cond = false;
  3141. symCheck->permittedSym = nullptr;
  3142. VisitIndirect<SymCheck>(expr, byteCodeGenerator, symCheck, &CheckInvertableExpr, nullptr);
  3143. return symCheck->result;
  3144. }
  3145. bool InvertableExprPlus(SymCheck* symCheck, ParseNode* expr, ByteCodeGenerator* byteCodeGenerator, Symbol* permittedSym)
  3146. {
  3147. symCheck->result = true;
  3148. symCheck->cond = true;
  3149. symCheck->permittedSym = permittedSym;
  3150. VisitIndirect<SymCheck>(expr, byteCodeGenerator, symCheck, &CheckInvertableExpr, nullptr);
  3151. return symCheck->result;
  3152. }
  3153. void CheckLocalVarDef(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  3154. {
  3155. Assert(pnode->nop == knopAsg);
  3156. if (pnode->sxBin.pnode1 != nullptr)
  3157. {
  3158. ParseNode *lhs = pnode->sxBin.pnode1;
  3159. if (lhs->nop == knopName)
  3160. {
  3161. Symbol *sym = lhs->sxPid.sym;
  3162. if (sym != nullptr)
  3163. {
  3164. sym->RecordDef();
  3165. }
  3166. }
  3167. }
  3168. }
  3169. ParseNode* ConstructInvertedStatement(ParseNode* stmt, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo,
  3170. ParseNode** outerStmtRef)
  3171. {
  3172. if (stmt == nullptr)
  3173. {
  3174. return nullptr;
  3175. }
  3176. ParseNode* cStmt;
  3177. if ((stmt->nop == knopAsg) || (stmt->nop == knopVarDecl))
  3178. {
  3179. ParseNode* rhs = nullptr;
  3180. ParseNode* lhs = nullptr;
  3181. if (stmt->nop == knopAsg)
  3182. {
  3183. rhs = stmt->sxBin.pnode2;
  3184. lhs = stmt->sxBin.pnode1;
  3185. }
  3186. else if (stmt->nop == knopVarDecl)
  3187. {
  3188. rhs = stmt->sxVar.pnodeInit;
  3189. }
  3190. ArenaAllocator* alloc = byteCodeGenerator->GetAllocator();
  3191. ParseNode* loopInvar = byteCodeGenerator->GetParser()->CreateTempNode(rhs);
  3192. loopInvar->location = funcInfo->NextVarRegister();
  3193. // Can't use a temp register here because the inversion happens at the parse tree level without generating
  3194. // any bytecode yet. All local non-temp registers need to be initialized for jitted loop bodies, and since this is
  3195. // not a user variable, track this register separately to have it be initialized at the top of the function.
  3196. funcInfo->nonUserNonTempRegistersToInitialize.Add(loopInvar->location);
  3197. // add temp node to list of initializers for new outer loop
  3198. if ((*outerStmtRef)->sxBin.pnode1 == nullptr)
  3199. {
  3200. (*outerStmtRef)->sxBin.pnode1 = loopInvar;
  3201. }
  3202. else
  3203. {
  3204. ParseNode* listNode = Parser::StaticCreateBinNode(knopList, nullptr, nullptr, alloc);
  3205. (*outerStmtRef)->sxBin.pnode2 = listNode;
  3206. listNode->sxBin.pnode1 = loopInvar;
  3207. *outerStmtRef = listNode;
  3208. }
  3209. ParseNode* tempName = byteCodeGenerator->GetParser()->CreateTempRef(loopInvar);
  3210. if (lhs != nullptr)
  3211. {
  3212. cStmt = Parser::StaticCreateBinNode(knopAsg, lhs, tempName, alloc);
  3213. }
  3214. else
  3215. {
  3216. // Use AddVarDeclNode to add the var to the function.
  3217. // Do not use CreateVarDeclNode which is meant to be used while parsing. It assumes that
  3218. // parser's internal data structures (m_ppnodeVar in particular) is at the "current" location.
  3219. cStmt = byteCodeGenerator->GetParser()->AddVarDeclNode(stmt->sxVar.pid, funcInfo->root);
  3220. cStmt->sxVar.pnodeInit = tempName;
  3221. cStmt->sxVar.sym = stmt->sxVar.sym;
  3222. }
  3223. }
  3224. else
  3225. {
  3226. cStmt = byteCodeGenerator->GetParser()->CopyPnode(stmt);
  3227. }
  3228. return cStmt;
  3229. }
  3230. ParseNode* ConstructInvertedLoop(ParseNode* innerLoop, ParseNode* outerLoop, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo)
  3231. {
  3232. ArenaAllocator* alloc = byteCodeGenerator->GetAllocator();
  3233. ParseNode* outerLoopC = Parser::StaticCreateNodeT<knopFor>(alloc);
  3234. outerLoopC->sxFor.pnodeInit = innerLoop->sxFor.pnodeInit;
  3235. outerLoopC->sxFor.pnodeCond = innerLoop->sxFor.pnodeCond;
  3236. outerLoopC->sxFor.pnodeIncr = innerLoop->sxFor.pnodeIncr;
  3237. outerLoopC->sxFor.pnodeBlock = innerLoop->sxFor.pnodeBlock;
  3238. outerLoopC->sxFor.pnodeInverted = nullptr;
  3239. ParseNode* innerLoopC = Parser::StaticCreateNodeT<knopFor>(alloc);
  3240. innerLoopC->sxFor.pnodeInit = outerLoop->sxFor.pnodeInit;
  3241. innerLoopC->sxFor.pnodeCond = outerLoop->sxFor.pnodeCond;
  3242. innerLoopC->sxFor.pnodeIncr = outerLoop->sxFor.pnodeIncr;
  3243. innerLoopC->sxFor.pnodeBlock = outerLoop->sxFor.pnodeBlock;
  3244. innerLoopC->sxFor.pnodeInverted = nullptr;
  3245. ParseNode* innerBod = Parser::StaticCreateBlockNode(alloc);
  3246. innerLoopC->sxFor.pnodeBody = innerBod;
  3247. innerBod->sxBlock.scope = innerLoop->sxFor.pnodeBody->sxBlock.scope;
  3248. ParseNode* outerBod = Parser::StaticCreateBlockNode(alloc);
  3249. outerLoopC->sxFor.pnodeBody = outerBod;
  3250. outerBod->sxBlock.scope = outerLoop->sxFor.pnodeBody->sxBlock.scope;
  3251. ParseNode* listNode = Parser::StaticCreateBinNode(knopList, nullptr, nullptr, alloc);
  3252. outerBod->sxBlock.pnodeStmt = listNode;
  3253. ParseNode* innerBodOriginal = innerLoop->sxFor.pnodeBody;
  3254. ParseNode* origStmt = innerBodOriginal->sxBlock.pnodeStmt;
  3255. if (origStmt->nop == knopList)
  3256. {
  3257. ParseNode* invertedStmt = nullptr;
  3258. while (origStmt->nop == knopList)
  3259. {
  3260. ParseNode* invertedItem = ConstructInvertedStatement(origStmt->sxBin.pnode1, byteCodeGenerator, funcInfo, &listNode);
  3261. if (invertedStmt != nullptr)
  3262. {
  3263. invertedStmt = invertedStmt->sxBin.pnode2 = byteCodeGenerator->GetParser()->CreateBinNode(knopList, invertedItem, nullptr);
  3264. }
  3265. else
  3266. {
  3267. invertedStmt = innerBod->sxBlock.pnodeStmt = byteCodeGenerator->GetParser()->CreateBinNode(knopList, invertedItem, nullptr);
  3268. }
  3269. origStmt = origStmt->sxBin.pnode2;
  3270. }
  3271. Assert(invertedStmt != nullptr);
  3272. invertedStmt->sxBin.pnode2 = ConstructInvertedStatement(origStmt, byteCodeGenerator, funcInfo, &listNode);
  3273. }
  3274. else
  3275. {
  3276. innerBod->sxBlock.pnodeStmt = ConstructInvertedStatement(origStmt, byteCodeGenerator, funcInfo, &listNode);
  3277. }
  3278. if (listNode->sxBin.pnode1 == nullptr)
  3279. {
  3280. listNode->sxBin.pnode1 = byteCodeGenerator->GetParser()->CreateTempNode(nullptr);
  3281. }
  3282. listNode->sxBin.pnode2 = innerLoopC;
  3283. return outerLoopC;
  3284. }
  3285. bool InvertableStmt(ParseNode* stmt, Symbol* outerVar, ParseNode* innerLoop, ParseNode* outerLoop, ByteCodeGenerator* byteCodeGenerator, SymCheck* symCheck)
  3286. {
  3287. if (stmt != nullptr)
  3288. {
  3289. ParseNode* lhs = nullptr;
  3290. ParseNode* rhs = nullptr;
  3291. if (stmt->nop == knopAsg)
  3292. {
  3293. lhs = stmt->sxBin.pnode1;
  3294. rhs = stmt->sxBin.pnode2;
  3295. }
  3296. else if (stmt->nop == knopVarDecl)
  3297. {
  3298. rhs = stmt->sxVar.pnodeInit;
  3299. }
  3300. if (lhs != nullptr)
  3301. {
  3302. if (lhs->nop == knopDot)
  3303. {
  3304. return false;
  3305. }
  3306. if (lhs->nop == knopName)
  3307. {
  3308. if ((lhs->sxPid.sym != nullptr) && (lhs->sxPid.sym->GetIsGlobal()))
  3309. {
  3310. return false;
  3311. }
  3312. }
  3313. else if (lhs->nop == knopIndex)
  3314. {
  3315. ParseNode* indexed = lhs->sxBin.pnode1;
  3316. ParseNode* index = lhs->sxBin.pnode2;
  3317. if ((index == nullptr) || (indexed == nullptr))
  3318. {
  3319. return false;
  3320. }
  3321. if ((indexed->nop != knopName) || (indexed->sxPid.sym == nullptr))
  3322. {
  3323. return false;
  3324. }
  3325. if (!InvertableExprPlus(symCheck, index, byteCodeGenerator, outerVar))
  3326. {
  3327. return false;
  3328. }
  3329. }
  3330. }
  3331. if (rhs != nullptr)
  3332. {
  3333. if (!InvertableExpr(symCheck, rhs, byteCodeGenerator))
  3334. {
  3335. return false;
  3336. }
  3337. }
  3338. else
  3339. {
  3340. if (!InvertableExpr(symCheck, stmt, byteCodeGenerator))
  3341. {
  3342. return false;
  3343. }
  3344. }
  3345. return true;
  3346. }
  3347. return false;
  3348. }
  3349. bool GatherInversionSyms(ParseNode* stmt, Symbol* outerVar, ParseNode* innerLoop, ByteCodeGenerator* byteCodeGenerator, SymCheck* symCheck)
  3350. {
  3351. if (stmt != nullptr)
  3352. {
  3353. ParseNode* lhs = nullptr;
  3354. Symbol* auxSym = nullptr;
  3355. if (stmt->nop == knopAsg)
  3356. {
  3357. lhs = stmt->sxBin.pnode1;
  3358. }
  3359. else if (stmt->nop == knopVarDecl)
  3360. {
  3361. auxSym = stmt->sxVar.sym;
  3362. }
  3363. if (lhs != nullptr)
  3364. {
  3365. if (lhs->nop == knopDot)
  3366. {
  3367. return false;
  3368. }
  3369. if (lhs->nop == knopName)
  3370. {
  3371. if ((lhs->sxPid.sym == nullptr) || (lhs->sxPid.sym->GetIsGlobal()))
  3372. {
  3373. return false;
  3374. }
  3375. else
  3376. {
  3377. auxSym = lhs->sxPid.sym;
  3378. }
  3379. }
  3380. }
  3381. if (auxSym != nullptr)
  3382. {
  3383. return symCheck->AddSymbol(auxSym);
  3384. }
  3385. }
  3386. return true;
  3387. }
  3388. bool InvertableBlock(ParseNode* block, Symbol* outerVar, ParseNode* innerLoop, ParseNode* outerLoop, ByteCodeGenerator* byteCodeGenerator,
  3389. SymCheck* symCheck)
  3390. {
  3391. if (block == nullptr)
  3392. {
  3393. return false;
  3394. }
  3395. if (!symCheck->AddSymbol(outerVar))
  3396. {
  3397. return false;
  3398. }
  3399. if (innerLoop->sxFor.pnodeBody->nop == knopBlock && innerLoop->sxFor.pnodeBody->sxBlock.HasBlockScopedContent()
  3400. || outerLoop->sxFor.pnodeBody->nop == knopBlock && outerLoop->sxFor.pnodeBody->sxBlock.HasBlockScopedContent())
  3401. {
  3402. // we can not invert loops if there are block scoped declarations inside
  3403. return false;
  3404. }
  3405. if ((block != nullptr) && (block->nop == knopBlock))
  3406. {
  3407. ParseNode* stmt = block->sxBlock.pnodeStmt;
  3408. while ((stmt != nullptr) && (stmt->nop == knopList))
  3409. {
  3410. if (!GatherInversionSyms(stmt->sxBin.pnode1, outerVar, innerLoop, byteCodeGenerator, symCheck))
  3411. {
  3412. return false;
  3413. }
  3414. stmt = stmt->sxBin.pnode2;
  3415. }
  3416. if (!GatherInversionSyms(stmt, outerVar, innerLoop, byteCodeGenerator, symCheck))
  3417. {
  3418. return false;
  3419. }
  3420. stmt = block->sxBlock.pnodeStmt;
  3421. while ((stmt != nullptr) && (stmt->nop == knopList))
  3422. {
  3423. if (!InvertableStmt(stmt->sxBin.pnode1, outerVar, innerLoop, outerLoop, byteCodeGenerator, symCheck))
  3424. {
  3425. return false;
  3426. }
  3427. stmt = stmt->sxBin.pnode2;
  3428. }
  3429. if (!InvertableStmt(stmt, outerVar, innerLoop, outerLoop, byteCodeGenerator, symCheck))
  3430. {
  3431. return false;
  3432. }
  3433. return (InvertableExprPlus(symCheck, innerLoop->sxFor.pnodeCond, byteCodeGenerator, nullptr) &&
  3434. InvertableExprPlus(symCheck, outerLoop->sxFor.pnodeCond, byteCodeGenerator, outerVar));
  3435. }
  3436. else
  3437. {
  3438. return false;
  3439. }
  3440. }
  3441. // Start of invert loop optimization.
  3442. // For now, find simple cases (only for loops around single assignment).
  3443. // Returns new AST for inverted loop; also returns in out param
  3444. // side effects level, if any that guards the new AST (old AST will be
  3445. // used if guard fails).
  3446. // Should only be called with loopNode representing top-level statement.
  3447. ParseNode* InvertLoop(ParseNode* outerLoop, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo)
  3448. {
  3449. if (byteCodeGenerator->GetScriptContext()->optimizationOverrides.GetSideEffects() != Js::SideEffects_None)
  3450. {
  3451. return nullptr;
  3452. }
  3453. SymCheck symCheck;
  3454. symCheck.Init();
  3455. if (outerLoop->nop == knopFor)
  3456. {
  3457. ParseNode* innerLoop = outerLoop->sxFor.pnodeBody;
  3458. if ((innerLoop == nullptr) || (innerLoop->nop != knopBlock))
  3459. {
  3460. return nullptr;
  3461. }
  3462. else
  3463. {
  3464. innerLoop = innerLoop->sxBlock.pnodeStmt;
  3465. }
  3466. if ((innerLoop != nullptr) && (innerLoop->nop == knopFor))
  3467. {
  3468. if ((outerLoop->sxFor.pnodeInit != nullptr) &&
  3469. (outerLoop->sxFor.pnodeInit->nop == knopVarDecl) &&
  3470. (outerLoop->sxFor.pnodeInit->sxVar.pnodeInit != nullptr) &&
  3471. (outerLoop->sxFor.pnodeInit->sxVar.pnodeInit->nop == knopInt) &&
  3472. (outerLoop->sxFor.pnodeIncr != nullptr) &&
  3473. ((outerLoop->sxFor.pnodeIncr->nop == knopIncPre) || (outerLoop->sxFor.pnodeIncr->nop == knopIncPost)) &&
  3474. (outerLoop->sxFor.pnodeIncr->sxUni.pnode1->nop == knopName) &&
  3475. (outerLoop->sxFor.pnodeInit->sxVar.pid == outerLoop->sxFor.pnodeIncr->sxUni.pnode1->sxPid.pid) &&
  3476. (innerLoop->sxFor.pnodeIncr != nullptr) &&
  3477. ((innerLoop->sxFor.pnodeIncr->nop == knopIncPre) || (innerLoop->sxFor.pnodeIncr->nop == knopIncPost)) &&
  3478. (innerLoop->sxFor.pnodeInit != nullptr) &&
  3479. (innerLoop->sxFor.pnodeInit->nop == knopVarDecl) &&
  3480. (innerLoop->sxFor.pnodeInit->sxVar.pnodeInit != nullptr) &&
  3481. (innerLoop->sxFor.pnodeInit->sxVar.pnodeInit->nop == knopInt) &&
  3482. (innerLoop->sxFor.pnodeIncr->sxUni.pnode1->nop == knopName) &&
  3483. (innerLoop->sxFor.pnodeInit->sxVar.pid == innerLoop->sxFor.pnodeIncr->sxUni.pnode1->sxPid.pid))
  3484. {
  3485. Symbol* outerVar = outerLoop->sxFor.pnodeInit->sxVar.sym;
  3486. Symbol* innerVar = innerLoop->sxFor.pnodeInit->sxVar.sym;
  3487. if ((outerVar != nullptr) && (innerVar != nullptr))
  3488. {
  3489. ParseNode* block = innerLoop->sxFor.pnodeBody;
  3490. if (InvertableBlock(block, outerVar, innerLoop, outerLoop, byteCodeGenerator, &symCheck))
  3491. {
  3492. return ConstructInvertedLoop(innerLoop, outerLoop, byteCodeGenerator, funcInfo);
  3493. }
  3494. }
  3495. }
  3496. }
  3497. }
  3498. return nullptr;
  3499. }
  3500. void SetAdditionalBindInfoForVariables(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  3501. {
  3502. Symbol *sym = pnode->sxVar.sym;
  3503. if (sym == nullptr)
  3504. {
  3505. return;
  3506. }
  3507. FuncInfo* func = byteCodeGenerator->TopFuncInfo();
  3508. if (func->IsGlobalFunction())
  3509. {
  3510. func->SetHasGlobalRef(true);
  3511. }
  3512. if (!sym->GetIsGlobal() && !sym->GetIsArguments() &&
  3513. (sym->GetScope() == func->GetBodyScope() || sym->GetScope() == func->GetParamScope() || sym->GetScope()->GetCanMerge()))
  3514. {
  3515. if (func->GetChildCallsEval())
  3516. {
  3517. func->SetHasLocalInClosure(true);
  3518. }
  3519. else
  3520. {
  3521. sym->RecordDef();
  3522. }
  3523. }
  3524. // If this decl does an assignment inside a loop body, then there's a chance
  3525. // that a jitted loop body will expect us to begin with a valid value in this var.
  3526. // So mark the sym as used so that we guarantee the var will at least get "undefined".
  3527. if (byteCodeGenerator->IsInLoop() &&
  3528. pnode->sxVar.pnodeInit)
  3529. {
  3530. sym->SetIsUsed(true);
  3531. }
  3532. }
  3533. // bind references to definitions (prefix pass)
  3534. void Bind(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  3535. {
  3536. if (pnode == nullptr)
  3537. {
  3538. return;
  3539. }
  3540. switch (pnode->nop)
  3541. {
  3542. case knopBreak:
  3543. case knopContinue:
  3544. byteCodeGenerator->AddTargetStmt(pnode->sxJump.pnodeTarget);
  3545. break;
  3546. case knopProg:
  3547. {
  3548. FuncInfo* globFuncInfo = byteCodeGenerator->StartBindGlobalStatements(pnode);
  3549. pnode->sxFnc.funcInfo = globFuncInfo;
  3550. AddFunctionsToScope(pnode->sxFnc.GetTopLevelScope(), byteCodeGenerator);
  3551. AddVarsToScope(pnode->sxFnc.pnodeVars, byteCodeGenerator);
  3552. // There are no args to add, but "eval" gets a this pointer.
  3553. byteCodeGenerator->SetNumberOfInArgs(!!(byteCodeGenerator->GetFlags() & fscrEvalCode));
  3554. if (!globFuncInfo->IsFakeGlobalFunction(byteCodeGenerator->GetFlags()))
  3555. {
  3556. // Global code: the root function is the global function.
  3557. byteCodeGenerator->SetRootFuncInfo(globFuncInfo);
  3558. }
  3559. else if (globFuncInfo->byteCodeFunction)
  3560. {
  3561. // If the current global code wasn't marked to be treated as global code (e.g. from deferred parsing),
  3562. // we don't need to send a register script event for it.
  3563. globFuncInfo->byteCodeFunction->SetIsTopLevel(false);
  3564. }
  3565. if (pnode->sxFnc.CallsEval())
  3566. {
  3567. globFuncInfo->SetCallsEval(true);
  3568. }
  3569. break;
  3570. }
  3571. case knopFncDecl:
  3572. // VisitFunctionsInScope has already done binding within the declared function. Here, just record the fact
  3573. // that the parent function has a local/global declaration in it.
  3574. BindFuncSymbol(pnode, byteCodeGenerator);
  3575. if (pnode->sxFnc.IsGenerator())
  3576. {
  3577. // Always assume generator functions escape since tracking them requires tracking
  3578. // the resulting generators in addition to the function.
  3579. byteCodeGenerator->FuncEscapes(byteCodeGenerator->TopFuncInfo()->GetBodyScope());
  3580. }
  3581. if (!pnode->sxFnc.IsDeclaration())
  3582. {
  3583. FuncInfo *funcInfo = byteCodeGenerator->TopFuncInfo();
  3584. if (!funcInfo->IsGlobalFunction() || (byteCodeGenerator->GetFlags() & fscrEval))
  3585. {
  3586. // In the case of a nested function expression, assumes that it escapes.
  3587. // We could try to analyze what it touches to be more precise.
  3588. byteCodeGenerator->FuncEscapes(funcInfo->GetBodyScope());
  3589. }
  3590. byteCodeGenerator->ProcessCapturedSyms(pnode);
  3591. }
  3592. else if (byteCodeGenerator->IsInLoop())
  3593. {
  3594. Symbol *funcSym = pnode->sxFnc.GetFuncSymbol();
  3595. if (funcSym)
  3596. {
  3597. Symbol *funcVarSym = funcSym->GetFuncScopeVarSym();
  3598. if (funcVarSym)
  3599. {
  3600. // We're going to write to the funcVarSym when we do the function instantiation,
  3601. // so treat the funcVarSym as used. That way, we know it will get undef-initialized at the
  3602. // top of the function, so a jitted loop body won't have any issue with boxing if
  3603. // the function instantiation isn't executed.
  3604. Assert(funcVarSym != funcSym);
  3605. funcVarSym->SetIsUsed(true);
  3606. }
  3607. }
  3608. }
  3609. break;
  3610. case knopThis:
  3611. case knopSuper:
  3612. {
  3613. FuncInfo *top = byteCodeGenerator->TopFuncInfo();
  3614. if (top->IsGlobalFunction() && !(byteCodeGenerator->GetFlags() & fscrEval))
  3615. {
  3616. top->SetHasGlobalRef(true);
  3617. }
  3618. else if (top->IsLambda())
  3619. {
  3620. byteCodeGenerator->MarkThisUsedInLambda();
  3621. }
  3622. // "this" should be loaded for both global and non-global functions
  3623. byteCodeGenerator->TopFuncInfo()->GetParsedFunctionBody()->SetHasThis(true);
  3624. break;
  3625. }
  3626. case knopName:
  3627. {
  3628. if (pnode->sxPid.sym == nullptr)
  3629. {
  3630. if (pnode->grfpn & fpnMemberReference)
  3631. {
  3632. // This is a member name. No binding.
  3633. break;
  3634. }
  3635. Symbol *sym = byteCodeGenerator->FindSymbol(pnode->sxPid.symRef, pnode->sxPid.pid);
  3636. if (sym)
  3637. {
  3638. // This is a named load, not just a reference, so if it's a nested function note that all
  3639. // the nested scopes escape.
  3640. Assert(!sym->GetDecl() || (pnode->sxPid.symRef && *pnode->sxPid.symRef));
  3641. Assert(!sym->GetDecl() || ((*pnode->sxPid.symRef)->GetDecl() == sym->GetDecl()));
  3642. pnode->sxPid.sym = sym;
  3643. if (sym->GetSymbolType() == STFunction &&
  3644. (!sym->GetIsGlobal() || (byteCodeGenerator->GetFlags() & fscrEval)))
  3645. {
  3646. byteCodeGenerator->FuncEscapes(sym->GetScope());
  3647. }
  3648. }
  3649. }
  3650. FuncInfo *top = byteCodeGenerator->TopFuncInfo();
  3651. if (pnode->sxPid.sym == nullptr || pnode->sxPid.sym->GetIsGlobal())
  3652. {
  3653. top->SetHasGlobalRef(true);
  3654. }
  3655. if (pnode->sxPid.sym)
  3656. {
  3657. pnode->sxPid.sym->SetIsUsed(true);
  3658. }
  3659. break;
  3660. }
  3661. case knopMember:
  3662. case knopMemberShort:
  3663. case knopObjectPatternMember:
  3664. if (pnode->sxBin.pnode1->nop == knopComputedName)
  3665. {
  3666. // Computed property name - cannot bind yet
  3667. break;
  3668. }
  3669. // fall through
  3670. case knopGetMember:
  3671. case knopSetMember:
  3672. {
  3673. // lhs is knopStr, rhs is expr
  3674. ParseNode *id = pnode->sxBin.pnode1;
  3675. if (id->nop == knopStr || id->nop == knopName)
  3676. {
  3677. byteCodeGenerator->AssignPropertyId(id->sxPid.pid);
  3678. id->sxPid.sym = nullptr;
  3679. id->sxPid.symRef = nullptr;
  3680. id->grfpn |= fpnMemberReference;
  3681. }
  3682. break;
  3683. }
  3684. // TODO: convert index over string to Get/Put Value
  3685. case knopIndex:
  3686. BindReference(pnode, byteCodeGenerator);
  3687. break;
  3688. case knopDot:
  3689. BindInstAndMember(pnode, byteCodeGenerator);
  3690. break;
  3691. case knopTryFinally:
  3692. byteCodeGenerator->SetHasFinally(true);
  3693. case knopTryCatch:
  3694. byteCodeGenerator->SetHasTry(true);
  3695. byteCodeGenerator->TopFuncInfo()->byteCodeFunction->SetDontInline(true);
  3696. byteCodeGenerator->AddTargetStmt(pnode);
  3697. break;
  3698. case knopAsg:
  3699. BindReference(pnode, byteCodeGenerator);
  3700. CheckLocalVarDef(pnode, byteCodeGenerator);
  3701. break;
  3702. case knopVarDecl:
  3703. // "arguments" symbol or decl w/o RHS may have been bound already; otherwise, do the binding here.
  3704. if (pnode->sxVar.sym == nullptr)
  3705. {
  3706. pnode->sxVar.sym = byteCodeGenerator->FindSymbol(pnode->sxVar.symRef, pnode->sxVar.pid);
  3707. }
  3708. SetAdditionalBindInfoForVariables(pnode, byteCodeGenerator);
  3709. break;
  3710. case knopConstDecl:
  3711. case knopLetDecl:
  3712. // "arguments" symbol or decl w/o RHS may have been bound already; otherwise, do the binding here.
  3713. if (!pnode->sxVar.sym)
  3714. {
  3715. AssertMsg(pnode->sxVar.symRef && *pnode->sxVar.symRef, "'const' and 'let' should be binded when we bind block");
  3716. pnode->sxVar.sym = *pnode->sxVar.symRef;
  3717. }
  3718. SetAdditionalBindInfoForVariables(pnode, byteCodeGenerator);
  3719. break;
  3720. case knopCall:
  3721. if (pnode->sxCall.isEvalCall && byteCodeGenerator->TopFuncInfo()->IsLambda())
  3722. {
  3723. byteCodeGenerator->MarkThisUsedInLambda();
  3724. }
  3725. // fallthrough
  3726. case knopTypeof:
  3727. case knopDelete:
  3728. BindReference(pnode, byteCodeGenerator);
  3729. break;
  3730. case knopRegExp:
  3731. pnode->sxPid.regexPatternIndex = byteCodeGenerator->TopFuncInfo()->GetParsedFunctionBody()->NewLiteralRegex();
  3732. break;
  3733. case knopComma:
  3734. pnode->sxBin.pnode1->SetNotEscapedUse();
  3735. break;
  3736. case knopBlock:
  3737. {
  3738. for (ParseNode *pnodeScope = pnode->sxBlock.pnodeScopes; pnodeScope; /* no increment */)
  3739. {
  3740. switch (pnodeScope->nop)
  3741. {
  3742. case knopFncDecl:
  3743. if (pnodeScope->sxFnc.IsDeclaration())
  3744. {
  3745. byteCodeGenerator->ProcessCapturedSyms(pnodeScope);
  3746. }
  3747. pnodeScope = pnodeScope->sxFnc.pnodeNext;
  3748. break;
  3749. case knopBlock:
  3750. pnodeScope = pnodeScope->sxBlock.pnodeNext;
  3751. break;
  3752. case knopCatch:
  3753. pnodeScope = pnodeScope->sxCatch.pnodeNext;
  3754. break;
  3755. case knopWith:
  3756. pnodeScope = pnodeScope->sxWith.pnodeNext;
  3757. break;
  3758. }
  3759. }
  3760. break;
  3761. }
  3762. }
  3763. }
  3764. void ByteCodeGenerator::ProcessCapturedSyms(ParseNode *pnode)
  3765. {
  3766. SymbolTable *capturedSyms = pnode->sxFnc.funcInfo->GetCapturedSyms();
  3767. if (capturedSyms)
  3768. {
  3769. FuncInfo *funcInfo = this->TopFuncInfo();
  3770. CapturedSymMap *capturedSymMap = funcInfo->EnsureCapturedSymMap();
  3771. ParseNode *pnodeStmt = this->GetCurrentTopStatement();
  3772. SList<Symbol*> *capturedSymList;
  3773. if (!pnodeStmt->CapturesSyms())
  3774. {
  3775. capturedSymList = Anew(this->alloc, SList<Symbol*>, this->alloc);
  3776. capturedSymMap->Add(pnodeStmt, capturedSymList);
  3777. pnodeStmt->SetCapturesSyms();
  3778. }
  3779. else
  3780. {
  3781. capturedSymList = capturedSymMap->Item(pnodeStmt);
  3782. }
  3783. capturedSyms->Map([&](Symbol *sym)
  3784. {
  3785. if (!sym->GetIsCommittedToSlot() && !sym->HasVisitedCapturingFunc())
  3786. {
  3787. capturedSymList->Prepend(sym);
  3788. sym->SetHasVisitedCapturingFunc();
  3789. }
  3790. });
  3791. }
  3792. }
  3793. void ByteCodeGenerator::MarkThisUsedInLambda()
  3794. {
  3795. // This is a lambda that refers to "this".
  3796. // Find the enclosing "normal" function and indicate that the lambda captures the enclosing function's "this".
  3797. FuncInfo *parent = this->FindEnclosingNonLambda();
  3798. parent->GetParsedFunctionBody()->SetHasThis(true);
  3799. if (!parent->IsGlobalFunction() || this->GetFlags() & fscrEval)
  3800. {
  3801. // If the enclosing function is non-global or eval global, it will put "this" in a closure slot.
  3802. parent->SetIsThisLexicallyCaptured();
  3803. Scope* scope = parent->IsGlobalFunction() ? parent->GetGlobalEvalBlockScope() : parent->GetBodyScope();
  3804. scope->SetHasLocalInClosure(true);
  3805. this->TopFuncInfo()->SetHasClosureReference(true);
  3806. }
  3807. this->TopFuncInfo()->SetHasCapturedThis();
  3808. }
  3809. void ByteCodeGenerator::FuncEscapes(Scope *scope)
  3810. {
  3811. while (scope)
  3812. {
  3813. Assert(scope->GetFunc());
  3814. scope->GetFunc()->SetEscapes(true);
  3815. scope = scope->GetEnclosingScope();
  3816. }
  3817. if (this->flags & fscrEval)
  3818. {
  3819. // If a function declared inside eval escapes, we'll need
  3820. // to invalidate the caller's cached scope.
  3821. this->funcEscapes = true;
  3822. }
  3823. }
  3824. bool ByteCodeGenerator::HasInterleavingDynamicScope(Symbol * sym) const
  3825. {
  3826. Js::PropertyId unused;
  3827. return this->InDynamicScope() &&
  3828. sym->GetScope() != this->FindScopeForSym(sym->GetScope(), nullptr, &unused, this->TopFuncInfo());
  3829. }
  3830. void CheckMaybeEscapedUse(ParseNode * pnode, ByteCodeGenerator * byteCodeGenerator, bool isCall = false)
  3831. {
  3832. if (pnode == nullptr)
  3833. {
  3834. return;
  3835. }
  3836. FuncInfo * topFunc = byteCodeGenerator->TopFuncInfo();
  3837. if (topFunc->IsGlobalFunction())
  3838. {
  3839. return;
  3840. }
  3841. switch (pnode->nop)
  3842. {
  3843. case knopAsg:
  3844. if (pnode->sxBin.pnode1->nop != knopName)
  3845. {
  3846. break;
  3847. }
  3848. // use of an assignment (e.g. (y = function() {}) + "1"), just make y an escaped use.
  3849. pnode = pnode->sxBin.pnode1;
  3850. isCall = false;
  3851. // fall-through
  3852. case knopName:
  3853. if (!isCall)
  3854. {
  3855. // Mark the name has having escaped use
  3856. if (pnode->sxPid.sym)
  3857. {
  3858. pnode->sxPid.sym->SetHasMaybeEscapedUse(byteCodeGenerator);
  3859. }
  3860. }
  3861. break;
  3862. case knopFncDecl:
  3863. // A function declaration has an unknown use (not assignment nor call),
  3864. // mark the function as having child escaped
  3865. topFunc->SetHasMaybeEscapedNestedFunc(DebugOnly(L"UnknownUse"));
  3866. break;
  3867. }
  3868. }
  3869. void CheckFuncAssignment(Symbol * sym, ParseNode * pnode2, ByteCodeGenerator * byteCodeGenerator)
  3870. {
  3871. if (pnode2 == nullptr)
  3872. {
  3873. return;
  3874. }
  3875. switch (pnode2->nop)
  3876. {
  3877. default:
  3878. CheckMaybeEscapedUse(pnode2, byteCodeGenerator);
  3879. break;
  3880. case knopFncDecl:
  3881. {
  3882. FuncInfo * topFunc = byteCodeGenerator->TopFuncInfo();
  3883. if (topFunc->IsGlobalFunction())
  3884. {
  3885. return;
  3886. }
  3887. // Use not as an assignment or assignment to an outer function's sym, or assigned to a formal
  3888. // or assigned to multiple names.
  3889. if (sym == nullptr
  3890. || sym->GetScope()->GetFunc() != topFunc)
  3891. {
  3892. topFunc->SetHasMaybeEscapedNestedFunc(DebugOnly(
  3893. sym == nullptr ? L"UnknownAssignment" :
  3894. (sym->GetScope()->GetFunc() != topFunc) ? L"CrossFuncAssignment" :
  3895. L"SomethingIsWrong!")
  3896. );
  3897. }
  3898. else
  3899. {
  3900. // TODO-STACK-NESTED-FUNC: Since we only support single def functions, we can still put the
  3901. // nested function on the stack and reuse even if the function goes out of the block scope.
  3902. // However, we cannot allocate frame display or slots on the stack if the function is
  3903. // declared in a loop, because there might be multiple functions referencing different
  3904. // iterations of the scope.
  3905. // For now, just disable everything.
  3906. Scope * funcParentScope = pnode2->sxFnc.funcInfo->GetBodyScope()->GetEnclosingScope();
  3907. while (sym->GetScope() != funcParentScope)
  3908. {
  3909. if (funcParentScope->GetMustInstantiate())
  3910. {
  3911. topFunc->SetHasMaybeEscapedNestedFunc(DebugOnly(L"CrossScopeAssignment"));
  3912. break;
  3913. }
  3914. funcParentScope->SetHasCrossScopeFuncAssignment();
  3915. funcParentScope = funcParentScope->GetEnclosingScope();
  3916. }
  3917. // Need to always detect interleaving dynamic scope ('with') for assignments
  3918. // as those may end up escaping into the 'with' scope.
  3919. // TODO: the with scope is marked as MustInstantiate late during byte code emit
  3920. // We could detect this using the loop above as well, by marking the with
  3921. // scope as must instantiate early, this is just less risky of a fix for RTM.
  3922. if (byteCodeGenerator->HasInterleavingDynamicScope(sym))
  3923. {
  3924. byteCodeGenerator->TopFuncInfo()->SetHasMaybeEscapedNestedFunc(DebugOnly(L"InterleavingDynamicScope"));
  3925. }
  3926. sym->SetHasFuncAssignment(byteCodeGenerator);
  3927. }
  3928. }
  3929. break;
  3930. };
  3931. }
  3932. inline bool ContainsSuperReference(ParseNodePtr pnode)
  3933. {
  3934. return (pnode->sxCall.pnodeTarget->nop == knopDot && pnode->sxCall.pnodeTarget->sxBin.pnode1->nop == knopSuper) // super.prop()
  3935. || (pnode->sxCall.pnodeTarget->nop == knopIndex && pnode->sxCall.pnodeTarget->sxBin.pnode1->nop == knopSuper); // super[prop]()
  3936. }
  3937. inline bool ContainsDirectSuper(ParseNodePtr pnode)
  3938. {
  3939. return pnode->sxCall.pnodeTarget->nop == knopSuper; // super()
  3940. }
  3941. // Assign permanent (non-temp) registers for the function.
  3942. // These include constants (null, 3.7, this) and locals that use registers as their home locations.
  3943. // Assign the location fields of parse nodes whose values are constants/locals with permanent/known registers.
  3944. // Re-usable expression temps are assigned during the final Emit pass.
  3945. void AssignRegisters(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
  3946. {
  3947. if (pnode == nullptr)
  3948. {
  3949. return;
  3950. }
  3951. Symbol *sym;
  3952. OpCode nop = pnode->nop;
  3953. switch (nop)
  3954. {
  3955. default:
  3956. {
  3957. uint flags = ParseNode::Grfnop(nop);
  3958. if (flags & fnopUni)
  3959. {
  3960. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  3961. }
  3962. else if (flags & fnopBin)
  3963. {
  3964. CheckMaybeEscapedUse(pnode->sxBin.pnode1, byteCodeGenerator);
  3965. CheckMaybeEscapedUse(pnode->sxBin.pnode2, byteCodeGenerator);
  3966. }
  3967. break;
  3968. }
  3969. case knopParamPattern:
  3970. byteCodeGenerator->AssignUndefinedConstRegister();
  3971. CheckMaybeEscapedUse(pnode->sxParamPattern.pnode1, byteCodeGenerator);
  3972. break;
  3973. case knopArrayPattern:
  3974. byteCodeGenerator->AssignUndefinedConstRegister();
  3975. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  3976. break;
  3977. case knopDot:
  3978. CheckMaybeEscapedUse(pnode->sxBin.pnode1, byteCodeGenerator);
  3979. break;
  3980. case knopMember:
  3981. case knopMemberShort:
  3982. case knopGetMember:
  3983. case knopSetMember:
  3984. CheckMaybeEscapedUse(pnode->sxBin.pnode2, byteCodeGenerator);
  3985. break;
  3986. case knopAsg:
  3987. {
  3988. Symbol * sym = pnode->sxBin.pnode1->nop == knopName ? pnode->sxBin.pnode1->sxPid.sym : nullptr;
  3989. CheckFuncAssignment(sym, pnode->sxBin.pnode2, byteCodeGenerator);
  3990. if (pnode->IsInList())
  3991. {
  3992. // Assignment in array literal
  3993. CheckMaybeEscapedUse(pnode->sxBin.pnode1, byteCodeGenerator);
  3994. }
  3995. if (byteCodeGenerator->IsES6DestructuringEnabled() && (pnode->sxBin.pnode1->nop == knopArrayPattern || pnode->sxBin.pnode1->nop == knopObjectPattern))
  3996. {
  3997. // Destructured arrays may have default values and need undefined.
  3998. byteCodeGenerator->AssignUndefinedConstRegister();
  3999. // Any rest parameter in a destructured array will need a 0 constant.
  4000. byteCodeGenerator->EnregisterConstant(0);
  4001. }
  4002. break;
  4003. }
  4004. case knopEllipsis:
  4005. if (byteCodeGenerator->InDestructuredPattern())
  4006. {
  4007. // Get a register for the rest array counter.
  4008. pnode->location = byteCodeGenerator->NextVarRegister();
  4009. // Any rest parameter in a destructured array will need a 0 constant.
  4010. byteCodeGenerator->EnregisterConstant(0);
  4011. }
  4012. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  4013. break;
  4014. case knopQmark:
  4015. CheckMaybeEscapedUse(pnode->sxTri.pnode1, byteCodeGenerator);
  4016. CheckMaybeEscapedUse(pnode->sxTri.pnode2, byteCodeGenerator);
  4017. CheckMaybeEscapedUse(pnode->sxTri.pnode3, byteCodeGenerator);
  4018. break;
  4019. case knopWith:
  4020. pnode->location = byteCodeGenerator->NextVarRegister();
  4021. CheckMaybeEscapedUse(pnode->sxWith.pnodeObj, byteCodeGenerator);
  4022. break;
  4023. case knopComma:
  4024. if (!pnode->IsNotEscapedUse())
  4025. {
  4026. // Only the last expr in comma expr escape. Mark it if it is escapable.
  4027. CheckMaybeEscapedUse(pnode->sxBin.pnode2, byteCodeGenerator);
  4028. }
  4029. break;
  4030. case knopFncDecl:
  4031. if (!byteCodeGenerator->TopFuncInfo()->IsGlobalFunction())
  4032. {
  4033. if (pnode->sxFnc.IsGenerator())
  4034. {
  4035. // Assume generators always escape; otherwise need to analyze if
  4036. // the return value of calls to generator function, the generator
  4037. // objects, escape.
  4038. FuncInfo* funcInfo = byteCodeGenerator->TopFuncInfo();
  4039. funcInfo->SetHasMaybeEscapedNestedFunc(DebugOnly(L"Generator"));
  4040. }
  4041. if (pnode->IsInList() && !pnode->IsNotEscapedUse())
  4042. {
  4043. byteCodeGenerator->TopFuncInfo()->SetHasMaybeEscapedNestedFunc(DebugOnly(L"InList"));
  4044. }
  4045. ParseNodePtr pnodeName = pnode->sxFnc.pnodeName;
  4046. if (pnodeName != nullptr)
  4047. {
  4048. // REVIEW: does this apply now that compat mode is gone?
  4049. // There is a weird case in compat mode where we may not have a sym assigned to a fnc decl's
  4050. // name node if it is a named function declare inside 'with' that also assigned to something else
  4051. // as well. Instead, We generate two knopFncDecl node one for parent function and one for the assignment.
  4052. // Only the top one gets a sym, not the inner one. The assignment in the 'with' will be using the inner
  4053. // one. Also we will detect that the assignment to a variable is an escape inside a 'with'.
  4054. // Since we need the sym in the fnc decl's name, we just detect the escape here as "WithScopeFuncName".
  4055. if (pnodeName->nop == knopVarDecl && pnodeName->sxVar.sym != nullptr)
  4056. {
  4057. // Unlike in CheckFuncAssignment, we don't check for interleaving
  4058. // dynamic scope ('with') here, because we also generate direct assignment for
  4059. // function decl's names
  4060. pnodeName->sxVar.sym->SetHasFuncAssignment(byteCodeGenerator);
  4061. // Function declaration in block scope and non-strict mode has a
  4062. // corresponding var sym that we assign to as well. Need to
  4063. // mark that symbol as has func assignment as well.
  4064. Symbol * functionScopeVarSym = pnodeName->sxVar.sym->GetFuncScopeVarSym();
  4065. if (functionScopeVarSym)
  4066. {
  4067. functionScopeVarSym->SetHasFuncAssignment(byteCodeGenerator);
  4068. }
  4069. }
  4070. else
  4071. {
  4072. // The function has multiple names, or assign to o.x or o::x
  4073. byteCodeGenerator->TopFuncInfo()->SetHasMaybeEscapedNestedFunc(DebugOnly(
  4074. pnodeName->nop == knopList ? L"MultipleFuncName" :
  4075. pnodeName->nop == knopDot ? L"PropFuncName" :
  4076. pnodeName->nop == knopVarDecl && pnodeName->sxVar.sym == nullptr ? L"WithScopeFuncName" :
  4077. L"WeirdFuncName"
  4078. ));
  4079. }
  4080. }
  4081. }
  4082. break;
  4083. case knopNew:
  4084. CheckMaybeEscapedUse(pnode->sxCall.pnodeTarget, byteCodeGenerator);
  4085. CheckMaybeEscapedUse(pnode->sxCall.pnodeArgs, byteCodeGenerator);
  4086. break;
  4087. case knopThrow:
  4088. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  4089. break;
  4090. // REVIEW: Technically, switch expr or case expr doesn't really escape as strict equal
  4091. // doesn't cause the function to escape.
  4092. case knopSwitch:
  4093. CheckMaybeEscapedUse(pnode->sxSwitch.pnodeVal, byteCodeGenerator);
  4094. break;
  4095. case knopCase:
  4096. CheckMaybeEscapedUse(pnode->sxCase.pnodeExpr, byteCodeGenerator);
  4097. break;
  4098. // REVIEW: Technically, the object for GetForInEnumerator doesn't escape, except when cached,
  4099. // which we can make work.
  4100. case knopForIn:
  4101. CheckMaybeEscapedUse(pnode->sxForInOrForOf.pnodeObj, byteCodeGenerator);
  4102. break;
  4103. case knopForOf:
  4104. byteCodeGenerator->AssignNullConstRegister();
  4105. byteCodeGenerator->AssignUndefinedConstRegister();
  4106. CheckMaybeEscapedUse(pnode->sxForInOrForOf.pnodeObj, byteCodeGenerator);
  4107. break;
  4108. case knopTrue:
  4109. pnode->location = byteCodeGenerator->AssignTrueConstRegister();
  4110. break;
  4111. case knopFalse:
  4112. pnode->location = byteCodeGenerator->AssignFalseConstRegister();
  4113. break;
  4114. case knopDecPost:
  4115. case knopIncPost:
  4116. case knopDecPre:
  4117. case knopIncPre:
  4118. byteCodeGenerator->EnregisterConstant(1);
  4119. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  4120. break;
  4121. case knopObject:
  4122. byteCodeGenerator->AssignNullConstRegister();
  4123. break;
  4124. case knopClassDecl:
  4125. {
  4126. FuncInfo * topFunc = byteCodeGenerator->TopFuncInfo();
  4127. topFunc->SetHasMaybeEscapedNestedFunc(DebugOnly(L"Class"));
  4128. // We may need undefined for the 'this', e.g. calling a class expression
  4129. byteCodeGenerator->AssignUndefinedConstRegister();
  4130. break;
  4131. }
  4132. case knopNull:
  4133. pnode->location = byteCodeGenerator->AssignNullConstRegister();
  4134. break;
  4135. case knopThis:
  4136. {
  4137. FuncInfo* func = byteCodeGenerator->TopFuncInfo();
  4138. pnode->location = func->AssignThisRegister();
  4139. if (func->IsLambda())
  4140. {
  4141. func = byteCodeGenerator->FindEnclosingNonLambda();
  4142. func->AssignThisRegister();
  4143. if (func->IsGlobalFunction() && !(byteCodeGenerator->GetFlags() & fscrEval))
  4144. {
  4145. byteCodeGenerator->AssignNullConstRegister();
  4146. }
  4147. }
  4148. // "this" should be loaded for both global and non global functions
  4149. if (func->IsGlobalFunction() && !(byteCodeGenerator->GetFlags() & fscrEval))
  4150. {
  4151. // We'll pass "null" to LdThis, to simulate "null" passed as "this" to the
  4152. // global function.
  4153. func->AssignNullConstRegister();
  4154. }
  4155. break;
  4156. }
  4157. case knopNewTarget:
  4158. {
  4159. FuncInfo* func = byteCodeGenerator->TopFuncInfo();
  4160. pnode->location = func->AssignNewTargetRegister();
  4161. FuncInfo* nonLambdaFunc = func;
  4162. if (func->IsLambda())
  4163. {
  4164. nonLambdaFunc = byteCodeGenerator->FindEnclosingNonLambda();
  4165. }
  4166. if (nonLambdaFunc != func || (func->IsGlobalFunction() && (byteCodeGenerator->GetFlags() & fscrEval)))
  4167. {
  4168. nonLambdaFunc->root->sxFnc.SetHasNewTargetReference();
  4169. nonLambdaFunc->AssignNewTargetRegister();
  4170. nonLambdaFunc->SetIsNewTargetLexicallyCaptured();
  4171. nonLambdaFunc->GetBodyScope()->SetHasLocalInClosure(true);
  4172. func->SetHasClosureReference(true);
  4173. }
  4174. break;
  4175. }
  4176. case knopSuper:
  4177. {
  4178. FuncInfo* func = byteCodeGenerator->TopFuncInfo();
  4179. pnode->location = func->AssignSuperRegister();
  4180. func->AssignThisRegister();
  4181. FuncInfo* nonLambdaFunc = func;
  4182. if (func->IsLambda())
  4183. {
  4184. // If this is a lambda inside a class member, the class member will need to load super.
  4185. nonLambdaFunc = byteCodeGenerator->FindEnclosingNonLambda();
  4186. nonLambdaFunc->root->sxFnc.SetHasSuperReference();
  4187. nonLambdaFunc->AssignSuperRegister();
  4188. nonLambdaFunc->AssignThisRegister();
  4189. nonLambdaFunc->SetIsSuperLexicallyCaptured();
  4190. if (nonLambdaFunc->IsClassConstructor())
  4191. {
  4192. func->AssignNewTargetRegister();
  4193. nonLambdaFunc->root->sxFnc.SetHasNewTargetReference();
  4194. nonLambdaFunc->AssignNewTargetRegister();
  4195. nonLambdaFunc->SetIsNewTargetLexicallyCaptured();
  4196. nonLambdaFunc->AssignUndefinedConstRegister();
  4197. }
  4198. nonLambdaFunc->GetBodyScope()->SetHasLocalInClosure(true);
  4199. func->SetHasClosureReference(true);
  4200. }
  4201. else
  4202. {
  4203. if (func->IsClassConstructor())
  4204. {
  4205. func->AssignNewTargetRegister();
  4206. }
  4207. }
  4208. if (nonLambdaFunc->IsGlobalFunction())
  4209. {
  4210. if (!(byteCodeGenerator->GetFlags() & fscrEval))
  4211. {
  4212. // Enable LdSuper for global function to support subsequent emission of call, dot, prop, etc., related to super.
  4213. func->AssignNullConstRegister();
  4214. nonLambdaFunc->AssignNullConstRegister();
  4215. }
  4216. }
  4217. else if (!func->IsClassMember())
  4218. {
  4219. func->AssignUndefinedConstRegister();
  4220. }
  4221. break;
  4222. }
  4223. case knopCall:
  4224. {
  4225. if (pnode->sxCall.pnodeTarget->nop != knopIndex &&
  4226. pnode->sxCall.pnodeTarget->nop != knopDot)
  4227. {
  4228. byteCodeGenerator->AssignUndefinedConstRegister();
  4229. }
  4230. bool containsDirectSuper = ContainsDirectSuper(pnode);
  4231. bool containsSuperReference = ContainsSuperReference(pnode);
  4232. if (containsDirectSuper)
  4233. {
  4234. pnode->sxCall.pnodeTarget->location = byteCodeGenerator->TopFuncInfo()->AssignSuperCtorRegister();
  4235. }
  4236. FuncInfo *funcInfo = byteCodeGenerator->TopFuncInfo();
  4237. if (containsDirectSuper || containsSuperReference)
  4238. {
  4239. // A super call requires 'this' to be available.
  4240. byteCodeGenerator->SetNeedEnvRegister();
  4241. byteCodeGenerator->AssignThisRegister();
  4242. FuncInfo* parent = funcInfo;
  4243. if (funcInfo->IsLambda())
  4244. {
  4245. // If this is a lambda inside a class member, the class member will need to load super.
  4246. parent = byteCodeGenerator->FindEnclosingNonLambda();
  4247. if (parent->root->sxFnc.IsClassMember())
  4248. {
  4249. // Set up super reference
  4250. if (containsSuperReference)
  4251. {
  4252. parent->root->sxFnc.SetHasSuperReference();
  4253. parent->AssignSuperRegister();
  4254. parent->SetIsSuperLexicallyCaptured();
  4255. }
  4256. else if (containsDirectSuper)
  4257. {
  4258. parent->root->sxFnc.SetHasDirectSuper();
  4259. parent->AssignSuperCtorRegister();
  4260. parent->SetIsSuperCtorLexicallyCaptured();
  4261. }
  4262. parent->GetBodyScope()->SetHasLocalInClosure(true);
  4263. funcInfo->SetHasClosureReference(true);
  4264. }
  4265. parent->AssignThisRegister();
  4266. byteCodeGenerator->MarkThisUsedInLambda();
  4267. }
  4268. // If this is a super call we need to have new.target
  4269. if (pnode->sxCall.pnodeTarget->nop == knopSuper)
  4270. {
  4271. byteCodeGenerator->AssignNewTargetRegister();
  4272. }
  4273. }
  4274. if (pnode->sxCall.isEvalCall)
  4275. {
  4276. if (!funcInfo->GetParsedFunctionBody()->IsReparsed())
  4277. {
  4278. Assert(funcInfo->IsGlobalFunction() || funcInfo->GetCallsEval());
  4279. funcInfo->SetCallsEval(true);
  4280. funcInfo->GetParsedFunctionBody()->SetCallsEval(true);
  4281. }
  4282. else
  4283. {
  4284. // On reparsing, load the state from function Body, instead of using the state on the parse node,
  4285. // as they might be different.
  4286. pnode->sxCall.isEvalCall = funcInfo->GetParsedFunctionBody()->GetCallsEval();
  4287. }
  4288. if (funcInfo->IsLambda() && pnode->sxCall.isEvalCall)
  4289. {
  4290. FuncInfo* nonLambdaParent = byteCodeGenerator->FindEnclosingNonLambda();
  4291. if (!nonLambdaParent->IsGlobalFunction() || (byteCodeGenerator->GetFlags() & fscrEval))
  4292. {
  4293. nonLambdaParent->AssignThisRegister();
  4294. }
  4295. }
  4296. // An eval call in a class member needs to load super.
  4297. if (funcInfo->root->sxFnc.IsClassMember())
  4298. {
  4299. funcInfo->AssignSuperRegister();
  4300. if (funcInfo->root->sxFnc.IsClassConstructor() && !funcInfo->root->sxFnc.IsBaseClassConstructor())
  4301. {
  4302. funcInfo->AssignSuperCtorRegister();
  4303. }
  4304. }
  4305. else if (funcInfo->IsLambda())
  4306. {
  4307. // If this is a lambda inside a class member, the class member will need to load super.
  4308. FuncInfo *parent = byteCodeGenerator->FindEnclosingNonLambda();
  4309. if (parent->root->sxFnc.IsClassMember())
  4310. {
  4311. parent->root->sxFnc.SetHasSuperReference();
  4312. parent->AssignSuperRegister();
  4313. if (parent->IsClassConstructor() && !parent->IsBaseClassConstructor())
  4314. {
  4315. parent->AssignSuperCtorRegister();
  4316. }
  4317. }
  4318. }
  4319. }
  4320. // Don't need to check pnode->sxCall.pnodeTarget even if it is a knopFncDecl,
  4321. // e.g. (function(){})();
  4322. // It is only used as a call, so don't count as an escape.
  4323. // Although not assigned to a slot, we will still able to box it by boxing
  4324. // all the stack function on the interpreter frame or the stack function link list
  4325. // on a jitted frame
  4326. break;
  4327. }
  4328. case knopInt:
  4329. pnode->location = byteCodeGenerator->EnregisterConstant(pnode->sxInt.lw);
  4330. break;
  4331. case knopFlt:
  4332. {
  4333. pnode->location = byteCodeGenerator->EnregisterDoubleConstant(pnode->sxFlt.dbl);
  4334. break;
  4335. }
  4336. case knopStr:
  4337. pnode->location = byteCodeGenerator->EnregisterStringConstant(pnode->sxPid.pid);
  4338. break;
  4339. case knopVarDecl:
  4340. case knopConstDecl:
  4341. case knopLetDecl:
  4342. {
  4343. sym = pnode->sxVar.sym;
  4344. Assert(sym != nullptr);
  4345. Assert(sym->GetScope()->GetEnclosingFunc() == byteCodeGenerator->TopFuncInfo());
  4346. if (pnode->sxVar.isBlockScopeFncDeclVar && sym->GetIsBlockVar())
  4347. {
  4348. break;
  4349. }
  4350. if (!sym->GetIsGlobal())
  4351. {
  4352. FuncInfo *funcInfo = byteCodeGenerator->TopFuncInfo();
  4353. // Check the function assignment for the sym that we have, even if we remap it to function level sym below
  4354. // as we are going assign to the original sym
  4355. CheckFuncAssignment(sym, pnode->sxVar.pnodeInit, byteCodeGenerator);
  4356. if (sym->GetIsCatch() || (pnode->nop == knopVarDecl && sym->GetIsBlockVar() && !pnode->sxVar.isBlockScopeFncDeclVar))
  4357. {
  4358. // The LHS of the var decl really binds to the local symbol, not the catch or let symbol.
  4359. // But the assignment will go to the catch or let symbol. Just assign a register to the local
  4360. // so that it can get initialized to undefined.
  4361. #if DBG
  4362. if (!sym->GetIsCatch())
  4363. {
  4364. // Catch cannot be at function scope and let and var at function scope is redeclaration error.
  4365. Assert(funcInfo->bodyScope != sym->GetScope() || !byteCodeGenerator->GetScriptContext()->GetConfig()->IsBlockScopeEnabled());
  4366. }
  4367. #endif
  4368. auto symName = sym->GetName();
  4369. sym = funcInfo->bodyScope->FindLocalSymbol(symName);
  4370. if (sym == nullptr)
  4371. {
  4372. sym = funcInfo->paramScope->FindLocalSymbol(symName);
  4373. }
  4374. Assert((sym && !sym->GetIsCatch() && !sym->GetIsBlockVar()));
  4375. }
  4376. // Don't give the declared var a register if it's in a closure, because the closure slot
  4377. // is its true "home". (Need to check IsGlobal again as the sym may have changed above.)
  4378. if (!sym->GetIsGlobal() && !sym->IsInSlot(funcInfo))
  4379. {
  4380. if (PHASE_TRACE(Js::DelayCapturePhase, funcInfo->byteCodeFunction))
  4381. {
  4382. if (sym->NeedsSlotAlloc(byteCodeGenerator->TopFuncInfo()))
  4383. {
  4384. Output::Print(L"--- DelayCapture: Delayed capturing symbol '%s' during initialization.\n", sym->GetName());
  4385. Output::Flush();
  4386. }
  4387. }
  4388. byteCodeGenerator->AssignRegister(sym);
  4389. }
  4390. }
  4391. else
  4392. {
  4393. Assert(byteCodeGenerator->TopFuncInfo()->IsGlobalFunction());
  4394. }
  4395. break;
  4396. }
  4397. case knopFor:
  4398. if ((pnode->sxFor.pnodeBody != nullptr) && (pnode->sxFor.pnodeBody->nop == knopBlock) &&
  4399. (pnode->sxFor.pnodeBody->sxBlock.pnodeStmt != nullptr) &&
  4400. (pnode->sxFor.pnodeBody->sxBlock.pnodeStmt->nop == knopFor) &&
  4401. (!byteCodeGenerator->IsInDebugMode()))
  4402. {
  4403. FuncInfo *funcInfo = byteCodeGenerator->TopFuncInfo();
  4404. pnode->sxFor.pnodeInverted = InvertLoop(pnode, byteCodeGenerator, funcInfo);
  4405. }
  4406. else
  4407. {
  4408. pnode->sxFor.pnodeInverted = nullptr;
  4409. }
  4410. break;
  4411. case knopName:
  4412. sym = pnode->sxPid.sym;
  4413. if (sym == nullptr)
  4414. {
  4415. Assert(pnode->sxPid.pid->GetPropertyId() != Js::Constants::NoProperty);
  4416. }
  4417. else
  4418. {
  4419. // Note: don't give a register to a local if it's in a closure, because then the closure
  4420. // is its true home.
  4421. if (!sym->GetIsGlobal() &&
  4422. !sym->GetIsMember() &&
  4423. byteCodeGenerator->TopFuncInfo() == sym->GetScope()->GetEnclosingFunc() &&
  4424. !sym->IsInSlot(byteCodeGenerator->TopFuncInfo()) &&
  4425. !sym->HasVisitedCapturingFunc())
  4426. {
  4427. if (PHASE_TRACE(Js::DelayCapturePhase, byteCodeGenerator->TopFuncInfo()->byteCodeFunction))
  4428. {
  4429. if (sym->NeedsSlotAlloc(byteCodeGenerator->TopFuncInfo()))
  4430. {
  4431. Output::Print(L"--- DelayCapture: Delayed capturing symbol '%s'.\n", sym->GetName());
  4432. Output::Flush();
  4433. }
  4434. }
  4435. // Local symbol being accessed in its own frame. Even if "with" or event
  4436. // handler semantics make the binding ambiguous, it has a home location,
  4437. // so assign it.
  4438. byteCodeGenerator->AssignRegister(sym);
  4439. // If we're in something like a "with" we'll need a scratch register to hold
  4440. // the multiple possible values of the property.
  4441. if (!byteCodeGenerator->HasInterleavingDynamicScope(sym))
  4442. {
  4443. // We're not in a dynamic scope, or our home scope is nested within the dynamic scope, so we
  4444. // don't have to do dynamic binding. Just use the home location for this reference.
  4445. pnode->location = sym->GetLocation();
  4446. }
  4447. }
  4448. }
  4449. if (pnode->IsInList() && !pnode->IsNotEscapedUse())
  4450. {
  4451. // A node that is in a list is assumed to be escape, unless marked otherwise.
  4452. // This includes array literal list/object literal list
  4453. CheckMaybeEscapedUse(pnode, byteCodeGenerator);
  4454. }
  4455. break;
  4456. case knopProg:
  4457. if (!byteCodeGenerator->HasParentScopeInfo())
  4458. {
  4459. // If we're compiling a nested deferred function, don't pop the scope stack,
  4460. // because we just want to leave it as-is for the emit pass.
  4461. PostVisitFunction(pnode, byteCodeGenerator);
  4462. }
  4463. break;
  4464. case knopReturn:
  4465. {
  4466. ParseNode *pnodeExpr = pnode->sxReturn.pnodeExpr;
  4467. CheckMaybeEscapedUse(pnodeExpr, byteCodeGenerator);
  4468. break;
  4469. }
  4470. case knopStrTemplate:
  4471. {
  4472. ParseNode* pnodeExprs = pnode->sxStrTemplate.pnodeSubstitutionExpressions;
  4473. if (pnodeExprs != nullptr)
  4474. {
  4475. while (pnodeExprs->nop == knopList)
  4476. {
  4477. Assert(pnodeExprs->sxBin.pnode1 != nullptr);
  4478. Assert(pnodeExprs->sxBin.pnode2 != nullptr);
  4479. CheckMaybeEscapedUse(pnodeExprs->sxBin.pnode1, byteCodeGenerator);
  4480. pnodeExprs = pnodeExprs->sxBin.pnode2;
  4481. }
  4482. // Also check the final element in the list
  4483. CheckMaybeEscapedUse(pnodeExprs, byteCodeGenerator);
  4484. }
  4485. if (pnode->sxStrTemplate.isTaggedTemplate)
  4486. {
  4487. pnode->location = byteCodeGenerator->EnregisterStringTemplateCallsiteConstant(pnode);
  4488. }
  4489. break;
  4490. }
  4491. case knopYieldLeaf:
  4492. byteCodeGenerator->AssignUndefinedConstRegister();
  4493. break;
  4494. case knopYield:
  4495. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  4496. break;
  4497. case knopYieldStar:
  4498. byteCodeGenerator->AssignNullConstRegister();
  4499. byteCodeGenerator->AssignUndefinedConstRegister();
  4500. CheckMaybeEscapedUse(pnode->sxUni.pnode1, byteCodeGenerator);
  4501. break;
  4502. }
  4503. }
  4504. // TODO[ianhall]: ApplyEnclosesArgs should be in ByteCodeEmitter.cpp but that becomes complicated because it depends on VisitIndirect
  4505. void PostCheckApplyEnclosesArgs(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, ApplyCheck* applyCheck);
  4506. void CheckApplyEnclosesArgs(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, ApplyCheck* applyCheck);
  4507. bool ApplyEnclosesArgs(ParseNode* fncDecl, ByteCodeGenerator* byteCodeGenerator)
  4508. {
  4509. if (byteCodeGenerator->IsInDebugMode())
  4510. {
  4511. // Inspection of the arguments object will be messed up if we do ApplyArgs.
  4512. return false;
  4513. }
  4514. if (!fncDecl->HasVarArguments()
  4515. && fncDecl->sxFnc.pnodeArgs == nullptr
  4516. && fncDecl->sxFnc.pnodeRest == nullptr
  4517. && fncDecl->sxFnc.nestedCount == 0)
  4518. {
  4519. ApplyCheck applyCheck;
  4520. applyCheck.matches = true;
  4521. applyCheck.sawApply = false;
  4522. applyCheck.insideApplyCall = false;
  4523. VisitIndirect<ApplyCheck>(fncDecl->sxFnc.pnodeBody, byteCodeGenerator, &applyCheck, &CheckApplyEnclosesArgs, &PostCheckApplyEnclosesArgs);
  4524. return applyCheck.matches&&applyCheck.sawApply;
  4525. }
  4526. return false;
  4527. }
  4528. // TODO[ianhall]: VisitClearTmpRegs should be in ByteCodeEmitter.cpp but that becomes complicated because it depends on VisitIndirect
  4529. void ClearTmpRegs(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, FuncInfo* emitFunc);
  4530. void VisitClearTmpRegs(ParseNode * pnode, ByteCodeGenerator * byteCodeGenerator, FuncInfo * funcInfo)
  4531. {
  4532. VisitIndirect<FuncInfo>(pnode, byteCodeGenerator, funcInfo, &ClearTmpRegs, nullptr);
  4533. }
  4534. Js::FunctionBody * ByteCodeGenerator::MakeGlobalFunctionBody(ParseNode *pnode)
  4535. {
  4536. Js::FunctionBody * func;
  4537. ENTER_PINNED_SCOPE(Js::PropertyRecordList, propertyRecordList);
  4538. propertyRecordList = EnsurePropertyRecordList();
  4539. func =
  4540. Js::FunctionBody::NewFromRecycler(
  4541. scriptContext,
  4542. Js::Constants::GlobalFunction,
  4543. Js::Constants::GlobalFunctionLength,
  4544. 0,
  4545. pnode->sxFnc.nestedCount,
  4546. m_utf8SourceInfo,
  4547. m_utf8SourceInfo->GetSrcInfo()->sourceContextInfo->sourceContextId,
  4548. pnode->sxFnc.functionId,
  4549. propertyRecordList,
  4550. Js::FunctionInfo::Attributes::None
  4551. #ifdef PERF_COUNTERS
  4552. , false /* is function from deferred deserialized proxy */
  4553. #endif
  4554. );
  4555. func->SetIsGlobalFunc(true);
  4556. scriptContext->RegisterDynamicFunctionReference(func);
  4557. LEAVE_PINNED_SCOPE();
  4558. return func;
  4559. }
  4560. /* static */
  4561. bool ByteCodeGenerator::NeedScopeObjectForArguments(FuncInfo *funcInfo, ParseNode *pnodeFnc)
  4562. {
  4563. // We can avoid creating a scope object with arguments present if:
  4564. bool dontNeedScopeObject =
  4565. // We have arguments, and
  4566. funcInfo->GetHasHeapArguments()
  4567. // Either we are in strict mode, or have strict mode formal semantics from a non-simple parameter list, and
  4568. && (funcInfo->GetIsStrictMode()
  4569. || !pnodeFnc->sxFnc.IsSimpleParameterList())
  4570. // Neither of the scopes are objects
  4571. && !funcInfo->paramScope->GetIsObject()
  4572. && !funcInfo->bodyScope->GetIsObject();
  4573. return funcInfo->GetHasHeapArguments()
  4574. // Regardless of the conditions above, we won't need a scope object if there aren't any formals.
  4575. && (pnodeFnc->sxFnc.pnodeArgs != nullptr || pnodeFnc->sxFnc.pnodeRest != nullptr)
  4576. && !dontNeedScopeObject;
  4577. }
  4578. Js::FunctionBody *ByteCodeGenerator::EnsureFakeGlobalFuncForUndefer(ParseNode *pnode)
  4579. {
  4580. Js::FunctionBody *func = scriptContext->GetFakeGlobalFuncForUndefer();
  4581. if (!func)
  4582. {
  4583. func = this->MakeGlobalFunctionBody(pnode);
  4584. scriptContext->SetFakeGlobalFuncForUndefer(func);
  4585. }
  4586. else
  4587. {
  4588. func->SetBoundPropertyRecords(EnsurePropertyRecordList());
  4589. }
  4590. if (pnode->sxFnc.GetStrictMode() != 0)
  4591. {
  4592. func->SetIsStrictMode();
  4593. }
  4594. return func;
  4595. }