zend_jit_trace.c 274 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend JIT |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Dmitry Stogov <dmitry@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. static zend_op_array dummy_op_array;
  19. static zend_jit_trace_info *zend_jit_traces = NULL;
  20. static const void **zend_jit_exit_groups = NULL;
  21. #define ZEND_JIT_COUNTER_NUM zend_jit_traces[0].root
  22. #define ZEND_JIT_TRACE_NUM zend_jit_traces[0].id
  23. #define ZEND_JIT_EXIT_NUM zend_jit_traces[0].exit_count
  24. #define ZEND_JIT_EXIT_COUNTERS zend_jit_traces[0].exit_counters
  25. #define ZEND_JIT_TRACE_STOP_DESCRIPTION(name, description) \
  26. description,
  27. static const char * zend_jit_trace_stop_description[] = {
  28. ZEND_JIT_TRACE_STOP(ZEND_JIT_TRACE_STOP_DESCRIPTION)
  29. };
  30. static zend_always_inline const char *zend_jit_trace_star_desc(uint8_t trace_flags)
  31. {
  32. if (trace_flags & ZEND_JIT_TRACE_START_LOOP) {
  33. return "loop";
  34. } else if (trace_flags & ZEND_JIT_TRACE_START_ENTER) {
  35. return "enter";
  36. } else if (trace_flags & ZEND_JIT_TRACE_START_RETURN) {
  37. return "return";
  38. } else {
  39. ZEND_UNREACHABLE();
  40. return "???";
  41. }
  42. }
  43. static int zend_jit_trace_startup(zend_bool reattached)
  44. {
  45. if (!reattached) {
  46. zend_jit_traces = (zend_jit_trace_info*)zend_shared_alloc(sizeof(zend_jit_trace_info) * JIT_G(max_root_traces));
  47. if (!zend_jit_traces) {
  48. return FAILURE;
  49. }
  50. zend_jit_exit_groups = (const void**)zend_shared_alloc(sizeof(void*) * (ZEND_JIT_TRACE_MAX_EXITS/ZEND_JIT_EXIT_POINTS_PER_GROUP));
  51. if (!zend_jit_exit_groups) {
  52. return FAILURE;
  53. }
  54. ZEND_JIT_TRACE_NUM = 1;
  55. ZEND_JIT_COUNTER_NUM = 0;
  56. ZEND_JIT_EXIT_NUM = 0;
  57. ZEND_JIT_EXIT_COUNTERS = 0;
  58. ZCSG(jit_traces) = zend_jit_traces;
  59. ZCSG(jit_exit_groups) = zend_jit_exit_groups;
  60. } else {
  61. zend_jit_traces = ZCSG(jit_traces);
  62. if (!zend_jit_traces) {
  63. return FAILURE;
  64. }
  65. zend_jit_exit_groups = ZCSG(jit_exit_groups);
  66. if (!zend_jit_exit_groups) {
  67. return FAILURE;
  68. }
  69. }
  70. memset(&dummy_op_array, 0, sizeof(dummy_op_array));
  71. dummy_op_array.fn_flags = ZEND_ACC_DONE_PASS_TWO;
  72. JIT_G(exit_counters) = calloc(JIT_G(max_exit_counters), 1);
  73. if (JIT_G(exit_counters) == NULL) {
  74. return FAILURE;
  75. }
  76. return SUCCESS;
  77. }
  78. static const void *zend_jit_trace_allocate_exit_group(uint32_t n)
  79. {
  80. dasm_State* dasm_state = NULL;
  81. const void *entry;
  82. char name[32];
  83. dasm_init(&dasm_state, DASM_MAXSECTION);
  84. dasm_setupglobal(&dasm_state, dasm_labels, zend_lb_MAX);
  85. dasm_setup(&dasm_state, dasm_actions);
  86. zend_jit_trace_exit_group_stub(&dasm_state, n);
  87. sprintf(name, "jit$$trace_exit_%d", n);
  88. entry = dasm_link_and_encode(&dasm_state, NULL, NULL, NULL, NULL, name, 0, SP_ADJ_JIT, SP_ADJ_NONE);
  89. dasm_free(&dasm_state);
  90. #ifdef HAVE_DISASM
  91. if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM) {
  92. uint32_t i;
  93. for (i = 0; i < ZEND_JIT_EXIT_POINTS_PER_GROUP; i++) {
  94. sprintf(name, "jit$$trace_exit_%d", n + i);
  95. zend_jit_disasm_add_symbol(name, (uintptr_t)entry + (i * ZEND_JIT_EXIT_POINTS_SPACING), ZEND_JIT_EXIT_POINTS_SPACING);
  96. }
  97. }
  98. #endif
  99. return entry;
  100. }
  101. static const void *zend_jit_trace_allocate_exit_point(uint32_t n)
  102. {
  103. const void *group = NULL;
  104. if (UNEXPECTED(n >= ZEND_JIT_TRACE_MAX_EXITS)) {
  105. return NULL;
  106. }
  107. do {
  108. group = zend_jit_trace_allocate_exit_group(ZEND_JIT_EXIT_NUM);
  109. if (!group) {
  110. return NULL;
  111. }
  112. zend_jit_exit_groups[ZEND_JIT_EXIT_NUM / ZEND_JIT_EXIT_POINTS_PER_GROUP] =
  113. group;
  114. ZEND_JIT_EXIT_NUM += ZEND_JIT_EXIT_POINTS_PER_GROUP;
  115. } while (n >= ZEND_JIT_EXIT_NUM);
  116. return (const void*)
  117. ((const char*)group +
  118. ((n % ZEND_JIT_EXIT_POINTS_PER_GROUP) * ZEND_JIT_EXIT_POINTS_SPACING));
  119. }
  120. static const void *zend_jit_trace_get_exit_addr(uint32_t n)
  121. {
  122. if (UNEXPECTED(n >= ZEND_JIT_EXIT_NUM)) {
  123. return zend_jit_trace_allocate_exit_point(n);
  124. }
  125. return (const void*)
  126. ((const char*)zend_jit_exit_groups[n / ZEND_JIT_EXIT_POINTS_PER_GROUP] +
  127. ((n % ZEND_JIT_EXIT_POINTS_PER_GROUP) * ZEND_JIT_EXIT_POINTS_SPACING));
  128. }
  129. #if ZEND_JIT_TARGET_ARM64
  130. static zend_jit_trace_info *zend_jit_get_current_trace_info(void)
  131. {
  132. return &zend_jit_traces[ZEND_JIT_TRACE_NUM];
  133. }
  134. static uint32_t zend_jit_trace_find_exit_point(const void* addr)
  135. {
  136. uint32_t n = ZEND_JIT_EXIT_NUM / ZEND_JIT_EXIT_POINTS_PER_GROUP;
  137. uint32_t i;
  138. for (i = 0; i < n; i++) {
  139. if ((const char*)addr >= (const char*)zend_jit_exit_groups[i]
  140. && (const char*)addr < (const char*)zend_jit_exit_groups[i] +
  141. (ZEND_JIT_EXIT_POINTS_PER_GROUP * ZEND_JIT_EXIT_POINTS_SPACING)) {
  142. return (i * ZEND_JIT_EXIT_POINTS_PER_GROUP) +
  143. ((const char*)addr - (const char*)zend_jit_exit_groups[i]) / ZEND_JIT_EXIT_POINTS_SPACING;
  144. }
  145. }
  146. return (uint32_t)-1;
  147. }
  148. #endif
  149. static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t flags)
  150. {
  151. zend_jit_trace_info *t = &zend_jit_traces[ZEND_JIT_TRACE_NUM];
  152. uint32_t exit_point;
  153. const zend_op_array *op_array;
  154. uint32_t stack_offset = (uint32_t)-1;
  155. uint32_t stack_size;
  156. zend_jit_trace_stack *stack = NULL;
  157. if (delayed_call_chain) {
  158. assert(to_opline != NULL); /* CALL and IP share the same register */
  159. flags |= ZEND_JIT_EXIT_RESTORE_CALL;
  160. }
  161. if (JIT_G(current_frame)) {
  162. op_array = &JIT_G(current_frame)->func->op_array;
  163. stack_size = op_array->last_var + op_array->T;
  164. if (stack_size) {
  165. stack = JIT_G(current_frame)->stack;
  166. do {
  167. if (STACK_TYPE(stack, stack_size-1) != IS_UNKNOWN
  168. || STACK_MEM_TYPE(stack, stack_size-1) != IS_UNKNOWN
  169. || STACK_REG(stack, stack_size-1) != ZREG_NONE) {
  170. break;
  171. }
  172. stack_size--;
  173. } while (stack_size);
  174. }
  175. } else {
  176. op_array = NULL;
  177. stack_size = 0;
  178. }
  179. /* Try to reuse exit points */
  180. if (to_opline != NULL && t->exit_count > 0) {
  181. uint32_t i = t->exit_count;
  182. do {
  183. i--;
  184. if (stack_size == 0
  185. || (t->exit_info[i].stack_size >= stack_size
  186. && memcmp(t->stack_map + t->exit_info[i].stack_offset, stack, stack_size * sizeof(zend_jit_trace_stack)) == 0)) {
  187. stack_offset = t->exit_info[i].stack_offset;
  188. if (t->exit_info[i].opline == to_opline
  189. && t->exit_info[i].flags == flags
  190. && t->exit_info[i].stack_size == stack_size) {
  191. return i;
  192. }
  193. }
  194. } while (i > 0);
  195. }
  196. exit_point = t->exit_count;
  197. if (exit_point < ZEND_JIT_TRACE_MAX_EXITS) {
  198. if (stack_size != 0 && stack_offset == (uint32_t)-1) {
  199. stack_offset = t->stack_map_size;
  200. t->stack_map_size += stack_size;
  201. // TODO: reduce number of reallocations ???
  202. t->stack_map = erealloc(t->stack_map, t->stack_map_size * sizeof(zend_jit_trace_stack));
  203. memcpy(t->stack_map + stack_offset, stack, stack_size * sizeof(zend_jit_trace_stack));
  204. }
  205. t->exit_count++;
  206. t->exit_info[exit_point].opline = to_opline;
  207. t->exit_info[exit_point].op_array = op_array;
  208. t->exit_info[exit_point].flags = flags;
  209. t->exit_info[exit_point].stack_size = stack_size;
  210. t->exit_info[exit_point].stack_offset = stack_offset;
  211. }
  212. return exit_point;
  213. }
  214. static void zend_jit_trace_add_code(const void *start, uint32_t size)
  215. {
  216. zend_jit_trace_info *t = &zend_jit_traces[ZEND_JIT_TRACE_NUM];
  217. t->code_start = start;
  218. t->code_size = size;
  219. }
  220. static uint32_t zend_jit_find_trace(const void *addr)
  221. {
  222. uint32_t i;
  223. for (i = 1; i < ZEND_JIT_TRACE_NUM; i++) {
  224. if (zend_jit_traces[i].code_start == addr) {
  225. return i;
  226. }
  227. }
  228. ZEND_UNREACHABLE();
  229. return 0;
  230. }
  231. static zend_string *zend_jit_trace_name(const zend_op_array *op_array, uint32_t lineno)
  232. {
  233. smart_str buf = {0};
  234. smart_str_appends(&buf, TRACE_PREFIX);
  235. smart_str_append_long(&buf, (zend_long)ZEND_JIT_TRACE_NUM);
  236. smart_str_appendc(&buf, '$');
  237. if (op_array->function_name) {
  238. if (op_array->scope) {
  239. smart_str_appendl(&buf, ZSTR_VAL(op_array->scope->name), ZSTR_LEN(op_array->scope->name));
  240. smart_str_appends(&buf, "::");
  241. smart_str_appendl(&buf, ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name));
  242. } else {
  243. smart_str_appendl(&buf, ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name));
  244. }
  245. } else if (op_array->filename) {
  246. smart_str_appendl(&buf, ZSTR_VAL(op_array->filename), ZSTR_LEN(op_array->filename));
  247. }
  248. smart_str_appendc(&buf, '$');
  249. smart_str_append_long(&buf, (zend_long)lineno);
  250. smart_str_0(&buf);
  251. return buf.s;
  252. }
  253. static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op *opline)
  254. {
  255. switch (opline->opcode) {
  256. case ZEND_IS_IDENTICAL:
  257. case ZEND_IS_NOT_IDENTICAL:
  258. case ZEND_IS_EQUAL:
  259. case ZEND_IS_NOT_EQUAL:
  260. case ZEND_IS_SMALLER:
  261. case ZEND_IS_SMALLER_OR_EQUAL:
  262. case ZEND_CASE:
  263. case ZEND_CASE_STRICT:
  264. case ZEND_ISSET_ISEMPTY_CV:
  265. case ZEND_ISSET_ISEMPTY_VAR:
  266. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  267. case ZEND_ISSET_ISEMPTY_PROP_OBJ:
  268. case ZEND_ISSET_ISEMPTY_STATIC_PROP:
  269. case ZEND_INSTANCEOF:
  270. case ZEND_TYPE_CHECK:
  271. case ZEND_DEFINED:
  272. case ZEND_IN_ARRAY:
  273. case ZEND_ARRAY_KEY_EXISTS:
  274. if (opline->result_type & (IS_SMART_BRANCH_JMPNZ | IS_SMART_BRANCH_JMPZ)) {
  275. /* smart branch */
  276. return 1;
  277. }
  278. break;
  279. case ZEND_JMPZNZ:
  280. case ZEND_JMPZ:
  281. case ZEND_JMPNZ:
  282. case ZEND_JMPZ_EX:
  283. case ZEND_JMPNZ_EX:
  284. case ZEND_JMP_SET:
  285. case ZEND_COALESCE:
  286. case ZEND_JMP_NULL:
  287. case ZEND_FE_RESET_R:
  288. case ZEND_FE_RESET_RW:
  289. case ZEND_ASSERT_CHECK:
  290. case ZEND_FE_FETCH_R:
  291. case ZEND_FE_FETCH_RW:
  292. case ZEND_SWITCH_LONG:
  293. case ZEND_SWITCH_STRING:
  294. case ZEND_MATCH:
  295. /* branch opcodes */
  296. return 1;
  297. case ZEND_NEW:
  298. if (opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL) {
  299. /* NEW may skip constructor without arguments */
  300. return 1;
  301. }
  302. break;
  303. case ZEND_CATCH:
  304. case ZEND_FAST_CALL:
  305. case ZEND_FAST_RET:
  306. case ZEND_GENERATOR_CREATE:
  307. case ZEND_GENERATOR_RETURN:
  308. case ZEND_EXIT:
  309. case ZEND_YIELD:
  310. case ZEND_YIELD_FROM:
  311. case ZEND_INCLUDE_OR_EVAL:
  312. case ZEND_MATCH_ERROR:
  313. /* unsupported */
  314. return 1;
  315. case ZEND_DO_FCALL:
  316. /* potentially polymorphic call */
  317. return 1;
  318. #if 0
  319. case ZEND_DO_UCALL:
  320. case ZEND_DO_FCALL_BY_NAME:
  321. /* monomorphic call */
  322. // TODO: recompilation may change target ???
  323. return 0;
  324. #endif
  325. case ZEND_RETURN_BY_REF:
  326. case ZEND_RETURN:
  327. /* return */
  328. return !JIT_G(current_frame) || TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame));
  329. default:
  330. break;
  331. }
  332. return 0;
  333. }
  334. static zend_always_inline uint32_t zend_jit_trace_type_to_info_ex(zend_uchar type, uint32_t info)
  335. {
  336. if (type == IS_UNKNOWN) {
  337. return info;
  338. }
  339. ZEND_ASSERT(info & (1 << type));
  340. if (type < IS_STRING) {
  341. return (1 << type);
  342. } else if (type != IS_ARRAY) {
  343. return (1 << type) | (info & (MAY_BE_RC1|MAY_BE_RCN));
  344. } else {
  345. return MAY_BE_ARRAY | (info & (MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY|MAY_BE_RC1|MAY_BE_RCN));
  346. }
  347. }
  348. static zend_always_inline uint32_t zend_jit_trace_type_to_info(zend_uchar type)
  349. {
  350. return zend_jit_trace_type_to_info_ex(type, -1);
  351. }
  352. static zend_always_inline zend_ssa_alias_kind zend_jit_var_may_alias(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t var)
  353. {
  354. if (var >= op_array->last_var) {
  355. return NO_ALIAS;
  356. } else if ((!op_array->function_name || (ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS))) {
  357. return SYMTABLE_ALIAS;
  358. } else if (ssa->vars) {
  359. return ssa->vars[var].alias;
  360. } else if (zend_string_equals_literal(op_array->vars[var], "http_response_header")) {
  361. return HTTP_RESPONSE_HEADER_ALIAS;
  362. }
  363. return NO_ALIAS;
  364. }
  365. static zend_always_inline void zend_jit_trace_add_op_guard(zend_ssa *tssa,
  366. int ssa_var,
  367. uint8_t op_type)
  368. {
  369. zend_ssa_var_info *info = &tssa->var_info[ssa_var];
  370. if ((info->type & (MAY_BE_ANY|MAY_BE_UNDEF)) != (1 << op_type)) {
  371. if (UNEXPECTED(tssa->vars[ssa_var].alias != NO_ALIAS)) {
  372. info->type |= MAY_BE_GUARD;
  373. } else {
  374. info->type = MAY_BE_GUARD | zend_jit_trace_type_to_info_ex(op_type, info->type);
  375. }
  376. }
  377. }
  378. #define ADD_OP_GUARD(_ssa_var, _op_type) do { \
  379. if (_ssa_var >= 0 && _op_type != IS_UNKNOWN) { \
  380. zend_jit_trace_add_op_guard(tssa, _ssa_var, _op_type); \
  381. } \
  382. } while (0)
  383. #define CHECK_OP_TRACE_TYPE(_var, _ssa_var, op_info, op_type) do { \
  384. if (op_type != IS_UNKNOWN) { \
  385. if ((op_info & MAY_BE_GUARD) != 0) { \
  386. if (!zend_jit_type_guard(&dasm_state, opline, _var, op_type)) { \
  387. goto jit_failure; \
  388. } \
  389. if (ssa->vars[_ssa_var].alias != NO_ALIAS) { \
  390. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(_var), IS_UNKNOWN, 1); \
  391. op_info = zend_jit_trace_type_to_info(op_type); \
  392. } else { \
  393. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(_var), op_type, 1); \
  394. op_info &= ~MAY_BE_GUARD; \
  395. ssa->var_info[_ssa_var].type &= op_info; \
  396. } \
  397. } \
  398. } \
  399. } while (0)
  400. #define ADD_OP1_TRACE_GUARD() \
  401. ADD_OP_GUARD(tssa->ops[idx].op1_use, op1_type)
  402. #define ADD_OP2_TRACE_GUARD() \
  403. ADD_OP_GUARD(tssa->ops[idx].op2_use, op2_type)
  404. #define ADD_OP1_DATA_TRACE_GUARD() \
  405. ADD_OP_GUARD(tssa->ops[idx+1].op1_use, op3_type)
  406. #define CHECK_OP1_TRACE_TYPE() \
  407. CHECK_OP_TRACE_TYPE(opline->op1.var, ssa_op->op1_use, op1_info, op1_type)
  408. #define CHECK_OP2_TRACE_TYPE() \
  409. CHECK_OP_TRACE_TYPE(opline->op2.var, ssa_op->op2_use, op2_info, op2_type)
  410. #define CHECK_OP1_DATA_TRACE_TYPE() \
  411. CHECK_OP_TRACE_TYPE((opline+1)->op1.var, (ssa_op+1)->op1_use, op1_data_info, op3_type)
  412. static zend_always_inline size_t zend_jit_trace_frame_size(const zend_op_array *op_array)
  413. {
  414. if (op_array && op_array->type == ZEND_USER_FUNCTION) {
  415. return ZEND_MM_ALIGNED_SIZE(offsetof(zend_jit_trace_stack_frame, stack) + ZEND_MM_ALIGNED_SIZE((op_array->last_var + op_array->T) * sizeof(zend_jit_trace_stack)));
  416. } else if (op_array) {
  417. return ZEND_MM_ALIGNED_SIZE(offsetof(zend_jit_trace_stack_frame, stack) + ZEND_MM_ALIGNED_SIZE(op_array->num_args * sizeof(zend_jit_trace_stack)));
  418. } else {
  419. return ZEND_MM_ALIGNED_SIZE(offsetof(zend_jit_trace_stack_frame, stack));
  420. }
  421. }
  422. static zend_jit_trace_stack_frame* zend_jit_trace_call_frame(zend_jit_trace_stack_frame *frame, const zend_op_array *op_array)
  423. {
  424. return (zend_jit_trace_stack_frame*)((char*)frame + zend_jit_trace_frame_size(op_array));
  425. }
  426. static zend_jit_trace_stack_frame* zend_jit_trace_ret_frame(zend_jit_trace_stack_frame *frame, const zend_op_array *op_array)
  427. {
  428. return (zend_jit_trace_stack_frame*)((char*)frame - zend_jit_trace_frame_size(op_array));
  429. }
  430. static void zend_jit_trace_send_type(const zend_op *opline, zend_jit_trace_stack_frame *call, zend_uchar type)
  431. {
  432. zend_jit_trace_stack *stack = call->stack;
  433. const zend_op_array *op_array = &call->func->op_array;
  434. uint32_t arg_num = opline->op2.num;
  435. if (arg_num > op_array->num_args) {
  436. return;
  437. }
  438. if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
  439. zend_arg_info *arg_info;
  440. ZEND_ASSERT(arg_num <= op_array->num_args);
  441. arg_info = &op_array->arg_info[arg_num-1];
  442. if (ZEND_TYPE_IS_SET(arg_info->type)) {
  443. if (!(ZEND_TYPE_FULL_MASK(arg_info->type) & (1u << type))) {
  444. return;
  445. }
  446. }
  447. }
  448. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), type, 1);
  449. }
  450. static bool zend_jit_needs_arg_dtor(const zend_function *func, uint32_t arg_num, zend_call_info *call_info)
  451. {
  452. if (func
  453. && func->type == ZEND_INTERNAL_FUNCTION
  454. && (func->internal_function.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0
  455. && arg_num < func->internal_function.num_args) {
  456. const zend_internal_arg_info *arg_info = &func->internal_function.arg_info[arg_num];
  457. if (ZEND_ARG_SEND_MODE(arg_info) == ZEND_SEND_BY_VAL
  458. && ZEND_TYPE_IS_SET(arg_info->type)
  459. && (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_ANY) != MAY_BE_ANY) {
  460. if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE
  461. && JIT_G(current_frame)
  462. && JIT_G(current_frame)->call
  463. && JIT_G(current_frame)->call->func) {
  464. uint32_t type = STACK_TYPE(JIT_G(current_frame)->call->stack, arg_num);
  465. if (type != IS_UNKNOWN
  466. && type < IS_STRING
  467. && ZEND_TYPE_FULL_MASK(arg_info->type) & (1u << type)) {
  468. return 0;
  469. }
  470. }
  471. if (call_info && arg_num < call_info->num_args && call_info->arg_info[arg_num].opline) {
  472. const zend_op *opline = call_info->arg_info[arg_num].opline;
  473. if (opline->opcode == ZEND_SEND_VAL && opline->op1_type == IS_CONST) {
  474. zval *zv = RT_CONSTANT(opline, opline->op1);
  475. if (!Z_REFCOUNTED_P(zv)) {
  476. uint32_t type = Z_TYPE_P(zv);
  477. // TODO: few functions (e.g. pcntl_exec) modify arrays in-place ???
  478. if (type != IS_ARRAY
  479. && (ZEND_TYPE_FULL_MASK(arg_info->type) & (1u << type))) {
  480. return 0;
  481. }
  482. }
  483. }
  484. }
  485. }
  486. }
  487. return 1;
  488. }
  489. static zend_ssa *zend_jit_trace_build_ssa(const zend_op_array *op_array, zend_script *script)
  490. {
  491. zend_jit_op_array_trace_extension *jit_extension;
  492. zend_ssa *ssa;
  493. jit_extension =
  494. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  495. jit_extension->func_info.num = 0;
  496. jit_extension->func_info.flags &= ZEND_FUNC_JIT_ON_FIRST_EXEC
  497. | ZEND_FUNC_JIT_ON_PROF_REQUEST
  498. | ZEND_FUNC_JIT_ON_HOT_COUNTERS
  499. | ZEND_FUNC_JIT_ON_HOT_TRACE;
  500. memset(&jit_extension->func_info.ssa, 0, sizeof(zend_func_info) - offsetof(zend_func_info, ssa));
  501. ssa = &jit_extension->func_info.ssa;
  502. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNC) {
  503. do {
  504. if (zend_jit_op_array_analyze1(op_array, script, ssa) != SUCCESS) {
  505. break;
  506. }
  507. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNCS) {
  508. if (zend_analyze_calls(&CG(arena), script, ZEND_CALL_TREE, (zend_op_array*)op_array, &jit_extension->func_info) != SUCCESS) {
  509. break;
  510. }
  511. jit_extension->func_info.call_map = zend_build_call_map(&CG(arena), &jit_extension->func_info, op_array);
  512. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  513. zend_init_func_return_info(op_array, script, &jit_extension->func_info.return_info);
  514. }
  515. }
  516. if (zend_jit_op_array_analyze2(op_array, script, ssa, 0) != SUCCESS) {
  517. break;
  518. }
  519. if (JIT_G(debug) & ZEND_JIT_DEBUG_SSA) {
  520. zend_dump_op_array(op_array, ZEND_DUMP_HIDE_UNREACHABLE|ZEND_DUMP_RC_INFERENCE|ZEND_DUMP_SSA, "JIT", ssa);
  521. }
  522. return ssa;
  523. } while (0);
  524. }
  525. memset(ssa, 0, sizeof(zend_ssa));
  526. ssa->cfg.blocks_count = 1;
  527. if (JIT_G(opt_level) == ZEND_JIT_LEVEL_INLINE) {
  528. zend_cfg cfg;
  529. void *checkpoint = zend_arena_checkpoint(CG(arena));
  530. if (zend_jit_build_cfg(op_array, &cfg) == SUCCESS) {
  531. ssa->cfg.flags = cfg.flags;
  532. } else{
  533. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  534. }
  535. /* TODO: move this to zend_cfg.c ? */
  536. if (!op_array->function_name) {
  537. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  538. }
  539. zend_arena_release(&CG(arena), checkpoint);
  540. }
  541. return ssa;
  542. }
  543. static void zend_jit_dump_trace(zend_jit_trace_rec *trace_buffer, zend_ssa *tssa);
  544. static void zend_jit_dump_exit_info(zend_jit_trace_info *t);
  545. static zend_always_inline int zend_jit_trace_op_len(const zend_op *opline)
  546. {
  547. int len;
  548. switch (opline->opcode) {
  549. case ZEND_ASSIGN_DIM:
  550. case ZEND_ASSIGN_OBJ:
  551. case ZEND_ASSIGN_STATIC_PROP:
  552. case ZEND_ASSIGN_DIM_OP:
  553. case ZEND_ASSIGN_OBJ_OP:
  554. case ZEND_ASSIGN_STATIC_PROP_OP:
  555. case ZEND_ASSIGN_OBJ_REF:
  556. case ZEND_ASSIGN_STATIC_PROP_REF:
  557. return 2; /* OP_DATA */
  558. case ZEND_RECV_INIT:
  559. len = 1;
  560. opline++;
  561. while (opline->opcode == ZEND_RECV_INIT) {
  562. len++;
  563. opline++;
  564. }
  565. return len;
  566. case ZEND_BIND_GLOBAL:
  567. len = 1;
  568. opline++;
  569. while (opline->opcode == ZEND_BIND_GLOBAL) {
  570. len++;
  571. opline++;
  572. }
  573. return len;
  574. // case ZEND_IS_IDENTICAL:
  575. // case ZEND_IS_NOT_IDENTICAL:
  576. // case ZEND_IS_EQUAL:
  577. // case ZEND_IS_NOT_EQUAL:
  578. // case ZEND_IS_SMALLER:
  579. // case ZEND_IS_SMALLER_OR_EQUAL:
  580. // case ZEND_CASE:
  581. // case ZEND_ISSET_ISEMPTY_CV:
  582. // case ZEND_ISSET_ISEMPTY_VAR:
  583. // case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  584. // case ZEND_ISSET_ISEMPTY_PROP_OBJ:
  585. // case ZEND_ISSET_ISEMPTY_STATIC_PROP:
  586. // case ZEND_INSTANCEOF:
  587. // case ZEND_TYPE_CHECK:
  588. // case ZEND_DEFINED:
  589. // case ZEND_IN_ARRAY:
  590. // case ZEND_ARRAY_KEY_EXISTS:
  591. default:
  592. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  593. return 2; /* JMPZ/JMPNZ */
  594. }
  595. return 1;
  596. }
  597. }
  598. static int zend_jit_trace_add_phis(zend_jit_trace_rec *trace_buffer, uint32_t ssa_vars_count, zend_ssa *tssa, zend_jit_trace_stack *stack)
  599. {
  600. const zend_op_array *op_array;
  601. zend_jit_trace_rec *p;
  602. int k, vars_count;
  603. zend_bitset use, def;
  604. uint32_t build_flags = ZEND_SSA_RC_INFERENCE | ZEND_SSA_USE_CV_RESULTS;
  605. uint32_t set_size;
  606. zend_ssa_phi *prev = NULL;
  607. int level = 0;
  608. ALLOCA_FLAG(use_heap);
  609. op_array = trace_buffer->op_array;
  610. set_size = zend_bitset_len(op_array->last_var + op_array->T);
  611. use = ZEND_BITSET_ALLOCA(set_size * 2, use_heap);
  612. memset(use, 0, set_size * 2 * ZEND_BITSET_ELM_SIZE);
  613. def = use + set_size;
  614. p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
  615. for (;;p++) {
  616. if (p->op == ZEND_JIT_TRACE_VM && level == 0) {
  617. const zend_op *opline = p->opline;
  618. int len;
  619. zend_dfg_add_use_def_op(op_array, opline, build_flags, use, def);
  620. len = zend_jit_trace_op_len(opline);
  621. while (len > 1) {
  622. opline++;
  623. if (opline->opcode != ZEND_OP_DATA) {
  624. zend_dfg_add_use_def_op(op_array, opline, build_flags, use, def);
  625. }
  626. len--;
  627. }
  628. } else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
  629. } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
  630. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  631. level++;
  632. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  633. if (level == 0) {
  634. // Phi for recursive calls and returns are not supported yet ???
  635. assert(0);
  636. } else {
  637. level--;
  638. }
  639. } else if (p->op == ZEND_JIT_TRACE_END) {
  640. break;
  641. }
  642. }
  643. zend_bitset_intersection(use, def, set_size);
  644. if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
  645. vars_count = op_array->last_var;
  646. } else {
  647. vars_count = op_array->last_var + op_array->T;
  648. }
  649. for (k = 0; k < vars_count; k++) {
  650. if (zend_bitset_in(use, k)) {
  651. zend_ssa_phi *phi = zend_arena_calloc(&CG(arena), 1,
  652. ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) +
  653. ZEND_MM_ALIGNED_SIZE(sizeof(int) * 2) +
  654. sizeof(void*) * 2);
  655. phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)));
  656. phi->sources[0] = STACK_VAR(stack, k);
  657. phi->sources[1] = -1;
  658. phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * 2));
  659. phi->pi = -1;
  660. phi->var = k;
  661. phi->ssa_var = ssa_vars_count;
  662. SET_STACK_VAR(stack, k, ssa_vars_count);
  663. ssa_vars_count++;
  664. phi->block = 1;
  665. if (prev) {
  666. prev->next = phi;
  667. } else {
  668. tssa->blocks[1].phis = phi;
  669. }
  670. prev = phi;
  671. }
  672. }
  673. free_alloca(use, use_heap);
  674. return ssa_vars_count;
  675. }
  676. static int zend_jit_trace_add_call_phis(zend_jit_trace_rec *trace_buffer, uint32_t ssa_vars_count, zend_ssa *tssa, zend_jit_trace_stack *stack)
  677. {
  678. zend_ssa_phi *prev = NULL;
  679. const zend_op_array *op_array = trace_buffer->op_array;
  680. const zend_op *opline = trace_buffer[1].opline;
  681. int count = opline - op_array->opcodes;
  682. int i;
  683. for(i = 0; i < count; i++) {
  684. zend_ssa_phi *phi = zend_arena_calloc(&CG(arena), 1,
  685. ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) +
  686. ZEND_MM_ALIGNED_SIZE(sizeof(int) * 2) +
  687. sizeof(void*) * 2);
  688. phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)));
  689. phi->sources[0] = STACK_VAR(stack, i);
  690. phi->sources[1] = -1;
  691. phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * 2));
  692. phi->pi = -1;
  693. phi->var = i;
  694. phi->ssa_var = ssa_vars_count;
  695. SET_STACK_VAR(stack, i, ssa_vars_count);
  696. ssa_vars_count++;
  697. phi->block = 1;
  698. if (prev) {
  699. prev->next = phi;
  700. } else {
  701. tssa->blocks[1].phis = phi;
  702. }
  703. prev = phi;
  704. }
  705. return ssa_vars_count;
  706. }
  707. static int zend_jit_trace_add_ret_phis(zend_jit_trace_rec *trace_buffer, uint32_t ssa_vars_count, zend_ssa *tssa, zend_jit_trace_stack *stack)
  708. {
  709. const zend_op *opline = trace_buffer[1].opline - 1;
  710. int i;
  711. if (RETURN_VALUE_USED(opline)) {
  712. zend_ssa_phi *phi = zend_arena_calloc(&CG(arena), 1,
  713. ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) +
  714. ZEND_MM_ALIGNED_SIZE(sizeof(int) * 2) +
  715. sizeof(void*) * 2);
  716. i = EX_VAR_TO_NUM(opline->result.var);
  717. phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)));
  718. phi->sources[0] = STACK_VAR(stack, i);
  719. phi->sources[1] = -1;
  720. phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * 2));
  721. phi->pi = -1;
  722. phi->var = i;
  723. phi->ssa_var = ssa_vars_count;
  724. SET_STACK_VAR(stack, i, ssa_vars_count);
  725. ssa_vars_count++;
  726. phi->block = 1;
  727. tssa->blocks[1].phis = phi;
  728. }
  729. return ssa_vars_count;
  730. }
  731. static int zend_jit_trace_copy_ssa_var_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op **tssa_opcodes, zend_ssa *tssa, int ssa_var)
  732. {
  733. int var, use;
  734. zend_ssa_op *op;
  735. zend_ssa_var_info *info;
  736. unsigned int no_val;
  737. zend_ssa_alias_kind alias;
  738. if (tssa->vars[ssa_var].phi_use_chain) {
  739. // TODO: this may be incorrect ???
  740. var = tssa->vars[ssa_var].phi_use_chain->ssa_var;
  741. } else {
  742. var = ssa_var;
  743. }
  744. use = tssa->vars[var].use_chain;
  745. if (use >= 0) {
  746. ZEND_ASSERT((tssa_opcodes[use] - op_array->opcodes) < op_array->last);
  747. op = ssa->ops + (tssa_opcodes[use] - op_array->opcodes);
  748. if (tssa->ops[use].op1_use == var) {
  749. no_val = ssa->vars[op->op1_use].no_val;
  750. alias = ssa->vars[op->op1_use].alias;
  751. info = ssa->var_info + op->op1_use;
  752. } else if (tssa->ops[use].op2_use == var) {
  753. no_val = ssa->vars[op->op2_use].no_val;
  754. alias = ssa->vars[op->op2_use].alias;
  755. info = ssa->var_info + op->op2_use;
  756. } else if (tssa->ops[use].result_use == var) {
  757. no_val = ssa->vars[op->result_use].no_val;
  758. alias = ssa->vars[op->result_use].alias;
  759. info = ssa->var_info + op->result_use;
  760. } else {
  761. assert(0);
  762. return 0;
  763. }
  764. tssa->vars[ssa_var].no_val = no_val;
  765. tssa->vars[ssa_var].alias = alias;
  766. memcpy(&tssa->var_info[ssa_var], info, sizeof(zend_ssa_var_info));
  767. return 1;
  768. }
  769. return 0;
  770. }
  771. static void zend_jit_trace_propagate_range(const zend_op_array *op_array, const zend_op **tssa_opcodes, zend_ssa *tssa, int ssa_var)
  772. {
  773. zend_ssa_range tmp;
  774. int def = tssa->vars[ssa_var].definition;
  775. if (tssa->vars[ssa_var].alias == NO_ALIAS
  776. && zend_inference_propagate_range(op_array, tssa, (zend_op*)tssa_opcodes[def], (zend_ssa_op*)&tssa->ops[def], ssa_var, &tmp)) {
  777. tssa->var_info[ssa_var].range.min = tmp.min;
  778. tssa->var_info[ssa_var].range.max = tmp.max;
  779. tssa->var_info[ssa_var].range.underflow = tmp.underflow;
  780. tssa->var_info[ssa_var].range.overflow = tmp.overflow;
  781. tssa->var_info[ssa_var].has_range = 1;
  782. }
  783. }
  784. static void zend_jit_trace_copy_ssa_var_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op **tssa_opcodes, zend_ssa *tssa, int ssa_var)
  785. {
  786. int def;
  787. zend_ssa_op *op;
  788. zend_ssa_var_info *info;
  789. unsigned int no_val;
  790. zend_ssa_alias_kind alias;
  791. def = tssa->vars[ssa_var].definition;
  792. if (def >= 0) {
  793. ZEND_ASSERT((tssa_opcodes[def] - op_array->opcodes) < op_array->last);
  794. op = ssa->ops + (tssa_opcodes[def] - op_array->opcodes);
  795. if (tssa->ops[def].op1_def == ssa_var) {
  796. no_val = ssa->vars[op->op1_def].no_val;
  797. alias = ssa->vars[op->op1_def].alias;
  798. info = ssa->var_info + op->op1_def;
  799. } else if (tssa->ops[def].op2_def == ssa_var) {
  800. no_val = ssa->vars[op->op2_def].no_val;
  801. alias = ssa->vars[op->op2_def].alias;
  802. info = ssa->var_info + op->op2_def;
  803. } else if (tssa->ops[def].result_def == ssa_var) {
  804. no_val = ssa->vars[op->result_def].no_val;
  805. alias = ssa->vars[op->result_def].alias;
  806. info = ssa->var_info + op->result_def;
  807. } else {
  808. assert(0);
  809. return;
  810. }
  811. tssa->vars[ssa_var].no_val = no_val;
  812. tssa->vars[ssa_var].alias = alias;
  813. if (!(info->type & MAY_BE_REF)) {
  814. zend_jit_trace_propagate_range(op_array, tssa_opcodes, tssa, ssa_var);
  815. }
  816. if (info->has_range) {
  817. if (tssa->var_info[ssa_var].has_range) {
  818. tssa->var_info[ssa_var].range.min = MAX(tssa->var_info[ssa_var].range.min, info->range.min);
  819. tssa->var_info[ssa_var].range.max = MIN(tssa->var_info[ssa_var].range.max, info->range.max);
  820. tssa->var_info[ssa_var].range.underflow = tssa->var_info[ssa_var].range.underflow && info->range.underflow;
  821. tssa->var_info[ssa_var].range.overflow = tssa->var_info[ssa_var].range.overflow && info->range.overflow;
  822. } else {
  823. tssa->var_info[ssa_var].has_range = 1;
  824. tssa->var_info[ssa_var].range = info->range;
  825. }
  826. }
  827. }
  828. }
  829. static int zend_jit_trace_restrict_ssa_var_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op **tssa_opcodes, zend_ssa *tssa, int ssa_var)
  830. {
  831. int def;
  832. zend_ssa_op *op;
  833. zend_ssa_var_info *info;
  834. def = tssa->vars[ssa_var].definition;
  835. if (def >= 0) {
  836. ZEND_ASSERT((tssa_opcodes[def] - op_array->opcodes) < op_array->last);
  837. op = ssa->ops + (tssa_opcodes[def] - op_array->opcodes);
  838. if (tssa->ops[def].op1_def == ssa_var) {
  839. info = ssa->var_info + op->op1_def;
  840. } else if (tssa->ops[def].op2_def == ssa_var) {
  841. info = ssa->var_info + op->op2_def;
  842. } else if (tssa->ops[def].result_def == ssa_var) {
  843. info = ssa->var_info + op->result_def;
  844. } else {
  845. assert(0);
  846. return 0;
  847. }
  848. tssa->var_info[ssa_var].type &= info->type;
  849. if (info->ce) {
  850. if (tssa->var_info[ssa_var].ce) {
  851. if (tssa->var_info[ssa_var].ce != info->ce) {
  852. if (instanceof_function(tssa->var_info[ssa_var].ce, info->ce)) {
  853. /* everything fine */
  854. } else if (instanceof_function(info->ce, tssa->var_info[ssa_var].ce)) {
  855. // TODO: TSSA may miss Pi() functions and corresponding instanceof() constraints ???
  856. } else {
  857. // TODO: classes may implement the same interface ???
  858. //ZEND_UNREACHABLE();
  859. }
  860. }
  861. tssa->var_info[ssa_var].is_instanceof =
  862. tssa->var_info[ssa_var].is_instanceof && info->is_instanceof;
  863. } else {
  864. tssa->var_info[ssa_var].ce = info->ce;
  865. tssa->var_info[ssa_var].is_instanceof = info->is_instanceof;
  866. }
  867. }
  868. if (info->has_range) {
  869. if (tssa->var_info[ssa_var].has_range) {
  870. tssa->var_info[ssa_var].range.min = MAX(tssa->var_info[ssa_var].range.min, info->range.min);
  871. tssa->var_info[ssa_var].range.max = MIN(tssa->var_info[ssa_var].range.max, info->range.max);
  872. tssa->var_info[ssa_var].range.underflow = tssa->var_info[ssa_var].range.underflow && info->range.underflow;
  873. tssa->var_info[ssa_var].range.overflow = tssa->var_info[ssa_var].range.overflow && info->range.overflow;
  874. } else {
  875. tssa->var_info[ssa_var].has_range = 1;
  876. tssa->var_info[ssa_var].range = info->range;
  877. }
  878. }
  879. return 1;
  880. }
  881. return 0;
  882. }
  883. static int find_return_ssa_var(zend_jit_trace_rec *p, zend_ssa_op *ssa_op)
  884. {
  885. while (1) {
  886. if (p->op == ZEND_JIT_TRACE_VM) {
  887. if (p->opline->opcode == ZEND_DO_UCALL
  888. || p->opline->opcode == ZEND_DO_FCALL_BY_NAME
  889. || p->opline->opcode == ZEND_DO_FCALL) {
  890. if (p->opline->result_type != IS_UNUSED) {
  891. return ssa_op->result_def;
  892. }
  893. }
  894. return -1;
  895. } else if (p->op >= ZEND_JIT_TRACE_OP1_TYPE && p->op <= ZEND_JIT_TRACE_VAL_INFO) {
  896. /*skip */
  897. } else {
  898. return -1;
  899. }
  900. p--;
  901. }
  902. }
  903. static const zend_op *zend_jit_trace_find_init_fcall_op(zend_jit_trace_rec *p, const zend_op_array *op_array)
  904. {
  905. if (!(p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL)) {
  906. p--;
  907. while (1) {
  908. if (p->op == ZEND_JIT_TRACE_VM) {
  909. if (p->opline->opcode == ZEND_INIT_FCALL
  910. || p->opline->opcode == ZEND_INIT_FCALL_BY_NAME
  911. || p->opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME
  912. || p->opline->opcode == ZEND_INIT_DYNAMIC_CALL
  913. || p->opline->opcode == ZEND_INIT_USER_CALL
  914. || p->opline->opcode == ZEND_NEW
  915. || p->opline->opcode == ZEND_INIT_METHOD_CALL
  916. || p->opline->opcode == ZEND_INIT_STATIC_METHOD_CALL) {
  917. return p->opline;
  918. }
  919. return NULL;
  920. } else if (p->op >= ZEND_JIT_TRACE_OP1_TYPE && p->op <= ZEND_JIT_TRACE_VAL_INFO) {
  921. /*skip */
  922. } else {
  923. return NULL;
  924. }
  925. p--;
  926. }
  927. } else {
  928. const zend_op *opline = NULL;
  929. int call_level = 0;
  930. p++;
  931. while (1) {
  932. if (p->op == ZEND_JIT_TRACE_VM) {
  933. opline = p->opline;
  934. break;
  935. } else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
  936. call_level++;
  937. /*skip */
  938. } else {
  939. return NULL;
  940. }
  941. p--;
  942. }
  943. if (opline) {
  944. while (opline > op_array->opcodes) {
  945. opline--;
  946. switch (opline->opcode) {
  947. case ZEND_INIT_FCALL:
  948. case ZEND_INIT_FCALL_BY_NAME:
  949. case ZEND_INIT_NS_FCALL_BY_NAME:
  950. case ZEND_INIT_METHOD_CALL:
  951. case ZEND_INIT_DYNAMIC_CALL:
  952. case ZEND_INIT_STATIC_METHOD_CALL:
  953. case ZEND_INIT_USER_CALL:
  954. case ZEND_NEW:
  955. if (call_level == 0) {
  956. return opline;
  957. }
  958. call_level--;
  959. break;
  960. case ZEND_DO_FCALL:
  961. case ZEND_DO_ICALL:
  962. case ZEND_DO_UCALL:
  963. case ZEND_DO_FCALL_BY_NAME:
  964. call_level++;
  965. break;
  966. }
  967. }
  968. }
  969. }
  970. return NULL;
  971. }
  972. static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, uint32_t var, uint32_t phi_var)
  973. {
  974. if ((tssa->var_info[phi_var].type & MAY_BE_ANY) == MAY_BE_LONG
  975. && !(tssa->var_info[var].type & MAY_BE_REF)) {
  976. int idx = tssa->vars[var].definition;
  977. if (idx >= 0) {
  978. if (tssa->ops[idx].op1_def == var) {
  979. const zend_op *opline = ssa_opcodes[idx];
  980. if (opline->opcode == ZEND_PRE_DEC
  981. || opline->opcode == ZEND_PRE_INC
  982. || opline->opcode == ZEND_POST_DEC
  983. || opline->opcode == ZEND_POST_INC) {
  984. if (tssa->ops[idx].op1_use >= 0
  985. && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_STRING)) {
  986. return 0;
  987. }
  988. if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  989. return 0;
  990. }
  991. return 1;
  992. } else if (opline->opcode == ZEND_ASSIGN_OP
  993. && (opline->extended_value == ZEND_ADD
  994. || opline->extended_value == ZEND_SUB
  995. || opline->extended_value == ZEND_MUL)) {
  996. if ((opline->op2_type & (IS_VAR|IS_CV))
  997. && tssa->ops[idx].op2_use >= 0
  998. && (tssa->var_info[tssa->ops[idx].op2_use].type & MAY_BE_REF)) {
  999. return 0;
  1000. }
  1001. if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  1002. return 0;
  1003. }
  1004. if (opline->op2_type == IS_CONST) {
  1005. zval *zv = RT_CONSTANT(opline, opline->op2);
  1006. if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) {
  1007. return 0;
  1008. }
  1009. } else if (!(tssa->var_info[tssa->ops[idx].op2_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  1010. return 0;
  1011. }
  1012. return 1;
  1013. }
  1014. }
  1015. if (tssa->ops[idx].result_def == var) {
  1016. const zend_op *opline = ssa_opcodes[idx];
  1017. if (opline->opcode == ZEND_ADD
  1018. || opline->opcode == ZEND_SUB
  1019. || opline->opcode == ZEND_MUL) {
  1020. if ((opline->op1_type & (IS_VAR|IS_CV))
  1021. && tssa->ops[idx].op1_use >= 0
  1022. && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) {
  1023. return 0;
  1024. }
  1025. if ((opline->op2_type & (IS_VAR|IS_CV))
  1026. && tssa->ops[idx].op2_use >= 0
  1027. && (tssa->var_info[tssa->ops[idx].op2_use].type & MAY_BE_REF)) {
  1028. return 0;
  1029. }
  1030. if (opline->op1_type == IS_CONST) {
  1031. zval *zv = RT_CONSTANT(opline, opline->op1);
  1032. if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) {
  1033. return 0;
  1034. }
  1035. } else if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  1036. return 0;
  1037. }
  1038. if (opline->op2_type == IS_CONST) {
  1039. zval *zv = RT_CONSTANT(opline, opline->op2);
  1040. if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) {
  1041. return 0;
  1042. }
  1043. } else if (!(tssa->var_info[tssa->ops[idx].op2_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  1044. return 0;
  1045. }
  1046. } else if (opline->opcode == ZEND_PRE_DEC
  1047. || opline->opcode == ZEND_PRE_INC
  1048. || opline->opcode == ZEND_POST_DEC
  1049. || opline->opcode == ZEND_POST_INC) {
  1050. if ((opline->op1_type & (IS_VAR|IS_CV))
  1051. && tssa->ops[idx].op1_use >= 0
  1052. && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) {
  1053. return 0;
  1054. }
  1055. if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  1056. return 0;
  1057. }
  1058. return 1;
  1059. }
  1060. }
  1061. }
  1062. }
  1063. return 0;
  1064. }
  1065. typedef struct _zend_tssa {
  1066. zend_ssa ssa;
  1067. const zend_op **tssa_opcodes;
  1068. int used_stack;
  1069. } zend_tssa;
  1070. static const zend_op _nop_opcode = {0};
  1071. static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uint32_t parent_trace, uint32_t exit_num, zend_script *script, const zend_op_array **op_arrays, int *num_op_arrays_ptr)
  1072. {
  1073. zend_ssa *tssa;
  1074. zend_ssa_op *ssa_ops, *op;
  1075. zend_ssa_var *ssa_vars;
  1076. zend_ssa_var_info *ssa_var_info;
  1077. const zend_op_array *op_array;
  1078. const zend_op *opline;
  1079. const zend_op **ssa_opcodes;
  1080. zend_jit_trace_rec *p;
  1081. int i, v, idx, len, ssa_ops_count, vars_count, ssa_vars_count;
  1082. zend_jit_trace_stack *stack;
  1083. uint32_t build_flags = ZEND_SSA_RC_INFERENCE | ZEND_SSA_USE_CV_RESULTS;
  1084. uint32_t optimization_level = 0;
  1085. int call_level, level, num_op_arrays, used_stack, max_used_stack;
  1086. size_t frame_size, stack_top, stack_size, stack_bottom;
  1087. zend_jit_op_array_trace_extension *jit_extension;
  1088. zend_ssa *ssa;
  1089. zend_jit_trace_stack_frame *frame, *top, *call;
  1090. zend_ssa_var_info return_value_info;
  1091. /* 1. Count number of TSSA opcodes;
  1092. * Count number of activation frames;
  1093. * Calculate size of abstract stack;
  1094. * Construct regular SSA for involved op_array */
  1095. op_array = trace_buffer->op_array;
  1096. stack_top = stack_size = zend_jit_trace_frame_size(op_array);
  1097. stack_bottom = 0;
  1098. p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
  1099. ssa_ops_count = 0;
  1100. call_level = 0;
  1101. level = 0;
  1102. num_op_arrays = 0;
  1103. /* Remember op_array to cleanup */
  1104. op_arrays[num_op_arrays++] = op_array;
  1105. /* Build SSA */
  1106. ssa = zend_jit_trace_build_ssa(op_array, script);
  1107. for (;;p++) {
  1108. if (p->op == ZEND_JIT_TRACE_VM) {
  1109. if (JIT_G(opt_level) < ZEND_JIT_LEVEL_OPT_FUNC) {
  1110. const zend_op *opline = p->opline;
  1111. switch (opline->opcode) {
  1112. case ZEND_INCLUDE_OR_EVAL:
  1113. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  1114. break;
  1115. case ZEND_FETCH_R:
  1116. case ZEND_FETCH_W:
  1117. case ZEND_FETCH_RW:
  1118. case ZEND_FETCH_FUNC_ARG:
  1119. case ZEND_FETCH_IS:
  1120. case ZEND_FETCH_UNSET:
  1121. case ZEND_UNSET_VAR:
  1122. case ZEND_ISSET_ISEMPTY_VAR:
  1123. if (opline->extended_value & ZEND_FETCH_LOCAL) {
  1124. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  1125. } else if ((opline->extended_value & (ZEND_FETCH_GLOBAL | ZEND_FETCH_GLOBAL_LOCK)) &&
  1126. !op_array->function_name) {
  1127. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  1128. }
  1129. break;
  1130. }
  1131. }
  1132. ssa_ops_count += zend_jit_trace_op_len(p->opline);
  1133. } else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
  1134. call_level++;
  1135. stack_top += zend_jit_trace_frame_size(p->op_array);
  1136. if (stack_top > stack_size) {
  1137. stack_size = stack_top;
  1138. }
  1139. } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
  1140. if (JIT_G(opt_level) < ZEND_JIT_LEVEL_OPT_FUNC) {
  1141. if (p->func != (zend_function*)&zend_pass_function
  1142. && (zend_string_equals_literal(p->func->common.function_name, "extract")
  1143. || zend_string_equals_literal(p->func->common.function_name, "compact")
  1144. || zend_string_equals_literal(p->func->common.function_name, "get_defined_vars"))) {
  1145. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  1146. }
  1147. }
  1148. frame_size = zend_jit_trace_frame_size(p->op_array);
  1149. if (call_level == 0) {
  1150. if (stack_top + frame_size > stack_size) {
  1151. stack_size = stack_top + frame_size;
  1152. }
  1153. } else {
  1154. call_level--;
  1155. stack_top -= frame_size;
  1156. }
  1157. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  1158. op_array = p->op_array;
  1159. if (call_level == 0) {
  1160. stack_top += zend_jit_trace_frame_size(op_array);
  1161. if (stack_top > stack_size) {
  1162. stack_size = stack_top;
  1163. }
  1164. } else {
  1165. call_level--;
  1166. }
  1167. level++;
  1168. jit_extension =
  1169. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  1170. ssa = &jit_extension->func_info.ssa;
  1171. if (ssa->cfg.blocks_count) {
  1172. /* pass */
  1173. } else if (num_op_arrays == ZEND_JIT_TRACE_MAX_FUNCS) {
  1174. /* Too many functions in single trace */
  1175. *num_op_arrays_ptr = num_op_arrays;
  1176. return NULL;
  1177. } else {
  1178. /* Remember op_array to cleanup */
  1179. op_arrays[num_op_arrays++] = op_array;
  1180. /* Build SSA */
  1181. ssa = zend_jit_trace_build_ssa(op_array, script);
  1182. }
  1183. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  1184. if (level == 0) {
  1185. stack_bottom += zend_jit_trace_frame_size(p->op_array);
  1186. jit_extension =
  1187. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  1188. ssa = &jit_extension->func_info.ssa;
  1189. if (ssa->cfg.blocks_count) {
  1190. /* pass */
  1191. } else if (num_op_arrays == ZEND_JIT_TRACE_MAX_FUNCS) {
  1192. /* Too many functions in single trace */
  1193. *num_op_arrays_ptr = num_op_arrays;
  1194. return NULL;
  1195. } else {
  1196. /* Remember op_array to cleanup */
  1197. op_arrays[num_op_arrays++] = op_array;
  1198. /* Build SSA */
  1199. ssa = zend_jit_trace_build_ssa(op_array, script);
  1200. }
  1201. } else {
  1202. stack_top -= zend_jit_trace_frame_size(op_array);
  1203. level--;
  1204. }
  1205. op_array = p->op_array;
  1206. } else if (p->op == ZEND_JIT_TRACE_END) {
  1207. break;
  1208. }
  1209. }
  1210. *num_op_arrays_ptr = num_op_arrays;
  1211. /* Allocate space for abstract stack */
  1212. JIT_G(current_frame) = frame = (zend_jit_trace_stack_frame*)((char*)zend_arena_alloc(&CG(arena), stack_bottom + stack_size) + stack_bottom);
  1213. /* 2. Construct TSSA */
  1214. tssa = zend_arena_calloc(&CG(arena), 1, sizeof(zend_tssa));
  1215. tssa->cfg.flags = ZEND_SSA_TSSA;
  1216. tssa->cfg.blocks = zend_arena_calloc(&CG(arena), 2, sizeof(zend_basic_block));
  1217. tssa->blocks = zend_arena_calloc(&CG(arena), 2, sizeof(zend_ssa_block));
  1218. tssa->cfg.predecessors = zend_arena_calloc(&CG(arena), 2, sizeof(int));
  1219. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  1220. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  1221. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  1222. tssa->cfg.blocks_count = 2;
  1223. tssa->cfg.edges_count = 2;
  1224. tssa->cfg.predecessors[0] = 0;
  1225. tssa->cfg.predecessors[1] = 1;
  1226. tssa->cfg.blocks[0].flags = ZEND_BB_START|ZEND_BB_REACHABLE;
  1227. tssa->cfg.blocks[0].successors_count = 1;
  1228. tssa->cfg.blocks[0].predecessors_count = 0;
  1229. tssa->cfg.blocks[0].successors = tssa->cfg.blocks[0].successors_storage;
  1230. tssa->cfg.blocks[0].successors[0] = 1;
  1231. tssa->cfg.blocks[0].flags = ZEND_BB_FOLLOW|ZEND_BB_TARGET|ZEND_BB_LOOP_HEADER|ZEND_BB_REACHABLE;
  1232. tssa->cfg.blocks[1].successors_count = 1;
  1233. tssa->cfg.blocks[1].predecessors_count = 2;
  1234. tssa->cfg.blocks[1].successors = tssa->cfg.blocks[1].successors_storage;
  1235. tssa->cfg.blocks[1].successors[1] = 1;
  1236. } else {
  1237. tssa->cfg.blocks_count = 1;
  1238. tssa->cfg.edges_count = 0;
  1239. tssa->cfg.blocks[0].flags = ZEND_BB_START|ZEND_BB_EXIT|ZEND_BB_REACHABLE;
  1240. tssa->cfg.blocks[0].successors_count = 0;
  1241. tssa->cfg.blocks[0].predecessors_count = 0;
  1242. }
  1243. ((zend_tssa*)tssa)->used_stack = -1;
  1244. if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) {
  1245. return tssa;
  1246. }
  1247. tssa->ops = ssa_ops = zend_arena_alloc(&CG(arena), ssa_ops_count * sizeof(zend_ssa_op));
  1248. memset(ssa_ops, -1, ssa_ops_count * sizeof(zend_ssa_op));
  1249. ssa_opcodes = zend_arena_calloc(&CG(arena), ssa_ops_count + 1, sizeof(zend_op*));
  1250. ((zend_tssa*)tssa)->tssa_opcodes = ssa_opcodes;
  1251. ssa_opcodes[ssa_ops_count] = &_nop_opcode;
  1252. op_array = trace_buffer->op_array;
  1253. if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
  1254. ssa_vars_count = op_array->last_var;
  1255. } else {
  1256. ssa_vars_count = op_array->last_var + op_array->T;
  1257. }
  1258. stack = frame->stack;
  1259. for (i = 0; i < ssa_vars_count; i++) {
  1260. SET_STACK_VAR(stack, i, i);
  1261. }
  1262. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) {
  1263. // TODO: For tracing, it's possible, to create pseudo Phi functions
  1264. // at the end of loop, without this additional pass (like LuaJIT) ???
  1265. ssa_vars_count = zend_jit_trace_add_phis(trace_buffer, ssa_vars_count, tssa, stack);
  1266. } else if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL) {
  1267. ssa_vars_count = zend_jit_trace_add_call_phis(trace_buffer, ssa_vars_count, tssa, stack);
  1268. } else if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  1269. ssa_vars_count = zend_jit_trace_add_ret_phis(trace_buffer, ssa_vars_count, tssa, stack);
  1270. }
  1271. p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
  1272. idx = 0;
  1273. level = 0;
  1274. for (;;p++) {
  1275. if (p->op == ZEND_JIT_TRACE_VM) {
  1276. opline = p->opline;
  1277. ssa_opcodes[idx] = opline;
  1278. ssa_vars_count = zend_ssa_rename_op(op_array, opline, idx, build_flags, ssa_vars_count, ssa_ops, (int*)stack);
  1279. idx++;
  1280. len = zend_jit_trace_op_len(p->opline);
  1281. while (len > 1) {
  1282. opline++;
  1283. ssa_opcodes[idx] = opline;
  1284. if (opline->opcode != ZEND_OP_DATA) {
  1285. ssa_vars_count = zend_ssa_rename_op(op_array, opline, idx, build_flags, ssa_vars_count, ssa_ops, (int*)stack);
  1286. }
  1287. idx++;
  1288. len--;
  1289. }
  1290. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  1291. frame = zend_jit_trace_call_frame(frame, op_array);
  1292. stack = frame->stack;
  1293. op_array = p->op_array;
  1294. level++;
  1295. if (ssa_vars_count >= ZEND_JIT_TRACE_MAX_SSA_VAR) {
  1296. return NULL;
  1297. }
  1298. ZEND_JIT_TRACE_SET_FIRST_SSA_VAR(p->info, ssa_vars_count);
  1299. for (i = 0; i < op_array->last_var; i++) {
  1300. SET_STACK_VAR(stack, i, ssa_vars_count++);
  1301. }
  1302. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  1303. op_array = p->op_array;
  1304. frame = zend_jit_trace_ret_frame(frame, op_array);
  1305. stack = frame->stack;
  1306. if (level == 0) {
  1307. if (ssa_vars_count >= ZEND_JIT_TRACE_MAX_SSA_VAR) {
  1308. return NULL;
  1309. }
  1310. ZEND_JIT_TRACE_SET_FIRST_SSA_VAR(p->info, ssa_vars_count);
  1311. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  1312. SET_STACK_VAR(stack, i, ssa_vars_count++);
  1313. }
  1314. } else {
  1315. level--;
  1316. }
  1317. } else if (p->op == ZEND_JIT_TRACE_END) {
  1318. break;
  1319. }
  1320. }
  1321. op_array = trace_buffer->op_array;
  1322. tssa->vars_count = ssa_vars_count;
  1323. tssa->vars = ssa_vars = zend_arena_calloc(&CG(arena), tssa->vars_count, sizeof(zend_ssa_var));
  1324. if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
  1325. vars_count = op_array->last_var;
  1326. } else {
  1327. vars_count = op_array->last_var + op_array->T;
  1328. }
  1329. i = 0;
  1330. while (i < vars_count) {
  1331. ssa_vars[i].var = i;
  1332. ssa_vars[i].scc = -1;
  1333. ssa_vars[i].definition = -1;
  1334. ssa_vars[i].use_chain = -1;
  1335. i++;
  1336. }
  1337. while (i < tssa->vars_count) {
  1338. ssa_vars[i].var = -1;
  1339. ssa_vars[i].scc = -1;
  1340. ssa_vars[i].definition = -1;
  1341. ssa_vars[i].use_chain = -1;
  1342. i++;
  1343. }
  1344. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  1345. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  1346. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  1347. /* Update Phi sources */
  1348. zend_ssa_phi *phi = tssa->blocks[1].phis;
  1349. while (phi) {
  1350. phi->sources[1] = STACK_VAR(stack, phi->var);
  1351. ssa_vars[phi->ssa_var].var = phi->var;
  1352. ssa_vars[phi->ssa_var].definition_phi = phi;
  1353. ssa_vars[phi->sources[0]].phi_use_chain = phi;
  1354. ssa_vars[phi->sources[1]].phi_use_chain = phi;
  1355. phi = phi->next;
  1356. }
  1357. }
  1358. /* 3. Compute use-def chains */
  1359. idx = (ssa_ops_count - 1);
  1360. op = ssa_ops + idx;
  1361. while (idx >= 0) {
  1362. opline = ssa_opcodes[idx];
  1363. if (op->op1_use >= 0) {
  1364. op->op1_use_chain = ssa_vars[op->op1_use].use_chain;
  1365. ssa_vars[op->op1_use].use_chain = idx;
  1366. }
  1367. if (op->op2_use >= 0 && op->op2_use != op->op1_use) {
  1368. op->op2_use_chain = ssa_vars[op->op2_use].use_chain;
  1369. ssa_vars[op->op2_use].use_chain = idx;
  1370. }
  1371. if (op->result_use >= 0 && op->result_use != op->op1_use && op->result_use != op->op2_use) {
  1372. op->res_use_chain = ssa_vars[op->result_use].use_chain;
  1373. ssa_vars[op->result_use].use_chain = idx;
  1374. }
  1375. if (op->op1_def >= 0) {
  1376. ssa_vars[op->op1_def].var = EX_VAR_TO_NUM(opline->op1.var);
  1377. ssa_vars[op->op1_def].definition = idx;
  1378. }
  1379. if (op->op2_def >= 0) {
  1380. ssa_vars[op->op2_def].var = EX_VAR_TO_NUM(opline->op2.var);
  1381. ssa_vars[op->op2_def].definition = idx;
  1382. }
  1383. if (op->result_def >= 0) {
  1384. ssa_vars[op->result_def].var = EX_VAR_TO_NUM(opline->result.var);
  1385. ssa_vars[op->result_def].definition = idx;
  1386. }
  1387. op--;
  1388. idx--;
  1389. }
  1390. /* 4. Type inference */
  1391. op_array = trace_buffer->op_array;
  1392. jit_extension =
  1393. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  1394. ssa = &jit_extension->func_info.ssa;
  1395. tssa->var_info = ssa_var_info = zend_arena_calloc(&CG(arena), tssa->vars_count, sizeof(zend_ssa_var_info));
  1396. if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
  1397. i = 0;
  1398. while (i < op_array->last_var) {
  1399. if (i < op_array->num_args) {
  1400. if (ssa->var_info
  1401. && zend_jit_trace_copy_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, i)) {
  1402. /* pass */
  1403. } else {
  1404. if (ssa->vars) {
  1405. ssa_vars[i].no_val = ssa->vars[i].no_val;
  1406. ssa_vars[i].alias = ssa->vars[i].alias;
  1407. } else {
  1408. ssa_vars[i].alias = zend_jit_var_may_alias(op_array, ssa, i);
  1409. }
  1410. if (op_array->arg_info) {
  1411. zend_arg_info *arg_info = &op_array->arg_info[i];
  1412. zend_class_entry *ce;
  1413. uint32_t tmp = zend_fetch_arg_info_type(script, arg_info, &ce);
  1414. if (ZEND_ARG_SEND_MODE(arg_info)) {
  1415. tmp |= MAY_BE_REF;
  1416. }
  1417. ssa_var_info[i].type = tmp;
  1418. ssa_var_info[i].ce = ce;
  1419. ssa_var_info[i].is_instanceof = 1;
  1420. } else {
  1421. ssa_var_info[i].type = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1422. }
  1423. }
  1424. } else {
  1425. if (ssa->vars) {
  1426. ssa_vars[i].no_val = ssa->vars[i].no_val;
  1427. ssa_vars[i].alias = ssa->vars[i].alias;
  1428. } else {
  1429. ssa_vars[i].alias = zend_jit_var_may_alias(op_array, ssa, i);
  1430. }
  1431. if (ssa_vars[i].alias == NO_ALIAS) {
  1432. ssa_var_info[i].type = MAY_BE_UNDEF;
  1433. } else {
  1434. ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1435. }
  1436. }
  1437. i++;
  1438. }
  1439. } else {
  1440. int parent_vars_count = 0;
  1441. zend_jit_trace_stack *parent_stack = NULL;
  1442. i = 0;
  1443. if (parent_trace) {
  1444. parent_vars_count = MIN(zend_jit_traces[parent_trace].exit_info[exit_num].stack_size,
  1445. op_array->last_var + op_array->T);
  1446. if (parent_vars_count) {
  1447. parent_stack =
  1448. zend_jit_traces[parent_trace].stack_map +
  1449. zend_jit_traces[parent_trace].exit_info[exit_num].stack_offset;
  1450. }
  1451. }
  1452. while (i < op_array->last_var + op_array->T) {
  1453. if (!ssa->var_info
  1454. || !zend_jit_trace_copy_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, i)) {
  1455. if (ssa->vars && i < ssa->vars_count) {
  1456. ssa_vars[i].alias = ssa->vars[i].alias;
  1457. } else {
  1458. ssa_vars[i].alias = zend_jit_var_may_alias(op_array, ssa, i);
  1459. }
  1460. if (i < op_array->last_var) {
  1461. ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1462. } else {
  1463. ssa_var_info[i].type = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1464. }
  1465. }
  1466. if (i < parent_vars_count) {
  1467. /* Initialize TSSA variable from parent trace */
  1468. zend_uchar op_type = STACK_TYPE(parent_stack, i);
  1469. if (op_type != IS_UNKNOWN) {
  1470. ssa_var_info[i].type &= zend_jit_trace_type_to_info(op_type);
  1471. if (!ssa_var_info[i].type
  1472. && op_type == IS_UNDEF
  1473. && i >= op_array->last_var) {
  1474. // TODO: It's better to use NULL instead of UNDEF for temporary variables
  1475. ssa_var_info[i].type |= MAY_BE_UNDEF;
  1476. }
  1477. }
  1478. }
  1479. i++;
  1480. }
  1481. }
  1482. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  1483. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  1484. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  1485. /* Propagate initial value through Phi functions */
  1486. zend_ssa_phi *phi = tssa->blocks[1].phis;
  1487. while (phi) {
  1488. if (!ssa->var_info
  1489. || !zend_jit_trace_copy_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, phi->ssa_var)) {
  1490. ssa_vars[phi->ssa_var].alias = ssa_vars[phi->sources[0]].alias;
  1491. ssa_var_info[phi->ssa_var].type = ssa_var_info[phi->sources[0]].type;
  1492. }
  1493. phi = phi->next;
  1494. }
  1495. }
  1496. frame = JIT_G(current_frame);
  1497. top = zend_jit_trace_call_frame(frame, op_array);
  1498. TRACE_FRAME_INIT(frame, op_array, 0, 0);
  1499. TRACE_FRAME_SET_RETURN_SSA_VAR(frame, -1);
  1500. frame->used_stack = 0;
  1501. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  1502. SET_STACK_TYPE(frame->stack, i, IS_UNKNOWN, 1);
  1503. }
  1504. memset(&return_value_info, 0, sizeof(return_value_info));
  1505. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) {
  1506. max_used_stack = used_stack = 0;
  1507. } else {
  1508. max_used_stack = used_stack = -1;
  1509. }
  1510. p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
  1511. idx = 0;
  1512. level = 0;
  1513. opline = NULL;
  1514. for (;;p++) {
  1515. if (p->op == ZEND_JIT_TRACE_VM) {
  1516. uint8_t orig_op1_type, orig_op2_type, op1_type, op2_type, op3_type;
  1517. uint8_t val_type = IS_UNKNOWN;
  1518. // zend_class_entry *op1_ce = NULL;
  1519. zend_class_entry *op2_ce = NULL;
  1520. opline = p->opline;
  1521. op1_type = orig_op1_type = p->op1_type;
  1522. op2_type = orig_op2_type = p->op2_type;
  1523. op3_type = p->op3_type;
  1524. if (op1_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
  1525. op1_type = IS_UNKNOWN;
  1526. }
  1527. if (op1_type != IS_UNKNOWN) {
  1528. op1_type &= ~IS_TRACE_PACKED;
  1529. }
  1530. if (op2_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
  1531. op2_type = IS_UNKNOWN;
  1532. }
  1533. if (op3_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
  1534. op3_type = IS_UNKNOWN;
  1535. }
  1536. if ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE) {
  1537. // op1_ce = (zend_class_entry*)(p+1)->ce;
  1538. p++;
  1539. }
  1540. if ((p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
  1541. op2_ce = (zend_class_entry*)(p+1)->ce;
  1542. p++;
  1543. }
  1544. if ((p+1)->op == ZEND_JIT_TRACE_VAL_INFO) {
  1545. val_type = (p+1)->op1_type;
  1546. p++;
  1547. }
  1548. switch (opline->opcode) {
  1549. case ZEND_ASSIGN_OP:
  1550. if (opline->extended_value == ZEND_POW
  1551. || opline->extended_value == ZEND_DIV) {
  1552. // TODO: check for division by zero ???
  1553. break;
  1554. }
  1555. if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
  1556. break;
  1557. }
  1558. ADD_OP1_TRACE_GUARD();
  1559. ADD_OP2_TRACE_GUARD();
  1560. break;
  1561. case ZEND_ASSIGN_DIM_OP:
  1562. if (opline->extended_value == ZEND_POW
  1563. || opline->extended_value == ZEND_DIV) {
  1564. // TODO: check for division by zero ???
  1565. break;
  1566. }
  1567. if (opline->result_type != IS_UNUSED) {
  1568. break;
  1569. }
  1570. if (op3_type != IS_UNKNOWN
  1571. && !zend_jit_supported_binary_op(
  1572. opline->extended_value, MAY_BE_ANY, (1<<op3_type))) {
  1573. break;
  1574. }
  1575. ZEND_FALLTHROUGH;
  1576. case ZEND_ASSIGN_DIM:
  1577. if (opline->op1_type == IS_CV) {
  1578. if ((opline+1)->op1_type == IS_CV
  1579. && (opline+1)->op1.var == opline->op1.var) {
  1580. /* skip $a[x] = $a; */
  1581. break;
  1582. }
  1583. ADD_OP1_DATA_TRACE_GUARD();
  1584. ADD_OP2_TRACE_GUARD();
  1585. ADD_OP1_TRACE_GUARD();
  1586. } else if (orig_op1_type != IS_UNKNOWN
  1587. && (orig_op1_type & IS_TRACE_INDIRECT)
  1588. && opline->result_type == IS_UNUSED) {
  1589. if (opline->opcode == ZEND_ASSIGN_DIM_OP) {
  1590. ADD_OP1_DATA_TRACE_GUARD();
  1591. }
  1592. ADD_OP2_TRACE_GUARD();
  1593. }
  1594. if (op1_type == IS_ARRAY
  1595. && ((opline->op2_type == IS_CONST
  1596. && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
  1597. || (opline->op2_type != IS_CONST
  1598. && op2_type == IS_LONG))) {
  1599. if (!(orig_op1_type & IS_TRACE_PACKED)) {
  1600. zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
  1601. if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
  1602. info->type |= MAY_BE_PACKED_GUARD;
  1603. info->type &= ~MAY_BE_ARRAY_PACKED;
  1604. }
  1605. } else if (opline->opcode == ZEND_ASSIGN_DIM_OP
  1606. && val_type != IS_UNKNOWN
  1607. && val_type != IS_UNDEF) {
  1608. zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
  1609. if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
  1610. info->type |= MAY_BE_PACKED_GUARD;
  1611. info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
  1612. }
  1613. }
  1614. }
  1615. break;
  1616. case ZEND_ASSIGN_OBJ_OP:
  1617. if (opline->extended_value == ZEND_POW
  1618. || opline->extended_value == ZEND_DIV) {
  1619. // TODO: check for division by zero ???
  1620. break;
  1621. }
  1622. if (opline->result_type != IS_UNUSED) {
  1623. break;
  1624. }
  1625. ZEND_FALLTHROUGH;
  1626. case ZEND_ASSIGN_OBJ:
  1627. case ZEND_PRE_INC_OBJ:
  1628. case ZEND_PRE_DEC_OBJ:
  1629. case ZEND_POST_INC_OBJ:
  1630. case ZEND_POST_DEC_OBJ:
  1631. if (opline->op2_type != IS_CONST
  1632. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  1633. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  1634. break;
  1635. }
  1636. if (opline->opcode == ZEND_ASSIGN_OBJ_OP) {
  1637. if (opline->op1_type == IS_CV
  1638. && (opline+1)->op1_type == IS_CV
  1639. && (opline+1)->op1.var == opline->op1.var) {
  1640. /* skip $a->prop += $a; */
  1641. break;
  1642. }
  1643. ADD_OP1_DATA_TRACE_GUARD();
  1644. }
  1645. ADD_OP1_TRACE_GUARD();
  1646. break;
  1647. case ZEND_CONCAT:
  1648. case ZEND_FAST_CONCAT:
  1649. if ((opline->op1_type == IS_CONST || orig_op1_type == IS_STRING)
  1650. && (opline->op2_type == IS_CONST || orig_op2_type == IS_STRING)) {
  1651. ADD_OP2_TRACE_GUARD();
  1652. ADD_OP1_TRACE_GUARD();
  1653. }
  1654. break;
  1655. case ZEND_IS_EQUAL:
  1656. case ZEND_IS_NOT_EQUAL:
  1657. case ZEND_IS_SMALLER:
  1658. case ZEND_IS_SMALLER_OR_EQUAL:
  1659. case ZEND_CASE:
  1660. case ZEND_IS_IDENTICAL:
  1661. case ZEND_IS_NOT_IDENTICAL:
  1662. case ZEND_CASE_STRICT:
  1663. case ZEND_BW_OR:
  1664. case ZEND_BW_AND:
  1665. case ZEND_BW_XOR:
  1666. case ZEND_SL:
  1667. case ZEND_SR:
  1668. case ZEND_MOD:
  1669. case ZEND_ADD:
  1670. case ZEND_SUB:
  1671. case ZEND_MUL:
  1672. // case ZEND_DIV: // TODO: check for division by zero ???
  1673. ADD_OP2_TRACE_GUARD();
  1674. ZEND_FALLTHROUGH;
  1675. case ZEND_ECHO:
  1676. case ZEND_STRLEN:
  1677. case ZEND_COUNT:
  1678. case ZEND_QM_ASSIGN:
  1679. case ZEND_FE_RESET_R:
  1680. case ZEND_FE_FETCH_R:
  1681. ADD_OP1_TRACE_GUARD();
  1682. break;
  1683. case ZEND_VERIFY_RETURN_TYPE:
  1684. if (opline->op1_type == IS_UNUSED) {
  1685. /* Always throws */
  1686. break;
  1687. }
  1688. if (opline->op1_type == IS_CONST) {
  1689. /* TODO Different instruction format, has return value */
  1690. break;
  1691. }
  1692. if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
  1693. /* Not worth bothering with */
  1694. break;
  1695. }
  1696. ADD_OP1_TRACE_GUARD();
  1697. break;
  1698. case ZEND_FETCH_DIM_FUNC_ARG:
  1699. if (!frame
  1700. || !frame->call
  1701. || !frame->call->func
  1702. || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(frame->call)) {
  1703. break;
  1704. }
  1705. ADD_OP2_TRACE_GUARD();
  1706. ADD_OP1_TRACE_GUARD();
  1707. break;
  1708. case ZEND_PRE_INC:
  1709. case ZEND_PRE_DEC:
  1710. case ZEND_POST_INC:
  1711. case ZEND_POST_DEC:
  1712. if (opline->op1_type != IS_CV) {
  1713. break;
  1714. }
  1715. ADD_OP1_TRACE_GUARD();
  1716. break;
  1717. case ZEND_ASSIGN:
  1718. if (opline->op1_type != IS_CV) {
  1719. break;
  1720. }
  1721. ADD_OP2_TRACE_GUARD();
  1722. if (op1_type != IS_UNKNOWN
  1723. && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) {
  1724. ADD_OP1_TRACE_GUARD();
  1725. }
  1726. break;
  1727. case ZEND_CAST:
  1728. if (opline->extended_value != op1_type) {
  1729. break;
  1730. }
  1731. ADD_OP1_TRACE_GUARD();
  1732. break;
  1733. case ZEND_JMPZ:
  1734. case ZEND_JMPNZ:
  1735. case ZEND_JMPZNZ:
  1736. case ZEND_JMPZ_EX:
  1737. case ZEND_JMPNZ_EX:
  1738. case ZEND_BOOL:
  1739. case ZEND_BOOL_NOT:
  1740. ADD_OP1_TRACE_GUARD();
  1741. break;
  1742. case ZEND_ISSET_ISEMPTY_CV:
  1743. if ((opline->extended_value & ZEND_ISEMPTY)) {
  1744. // TODO: support for empty() ???
  1745. break;
  1746. }
  1747. ADD_OP1_TRACE_GUARD();
  1748. break;
  1749. case ZEND_IN_ARRAY:
  1750. if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
  1751. break;
  1752. }
  1753. ADD_OP1_TRACE_GUARD();
  1754. break;
  1755. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  1756. if ((opline->extended_value & ZEND_ISEMPTY)) {
  1757. // TODO: support for empty() ???
  1758. break;
  1759. }
  1760. ZEND_FALLTHROUGH;
  1761. case ZEND_FETCH_DIM_R:
  1762. case ZEND_FETCH_DIM_IS:
  1763. case ZEND_FETCH_LIST_R:
  1764. ADD_OP1_TRACE_GUARD();
  1765. ADD_OP2_TRACE_GUARD();
  1766. if (op1_type == IS_ARRAY
  1767. && opline->op1_type != IS_CONST
  1768. && ((opline->op2_type == IS_CONST
  1769. && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
  1770. || (opline->op2_type != IS_CONST
  1771. && op2_type == IS_LONG))) {
  1772. zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
  1773. if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
  1774. info->type |= MAY_BE_PACKED_GUARD;
  1775. if (orig_op1_type & IS_TRACE_PACKED) {
  1776. info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
  1777. } else {
  1778. info->type &= ~MAY_BE_ARRAY_PACKED;
  1779. }
  1780. }
  1781. }
  1782. break;
  1783. case ZEND_FETCH_DIM_W:
  1784. case ZEND_FETCH_DIM_RW:
  1785. // case ZEND_FETCH_DIM_UNSET:
  1786. case ZEND_FETCH_LIST_W:
  1787. if (opline->op1_type != IS_CV
  1788. && (orig_op1_type == IS_UNKNOWN
  1789. || !(orig_op1_type & IS_TRACE_INDIRECT))) {
  1790. break;
  1791. }
  1792. ADD_OP1_TRACE_GUARD();
  1793. ADD_OP2_TRACE_GUARD();
  1794. if (op1_type == IS_ARRAY
  1795. && !(orig_op1_type & IS_TRACE_PACKED)
  1796. && ((opline->op2_type == IS_CONST
  1797. && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
  1798. || (opline->op2_type != IS_CONST
  1799. && op2_type == IS_LONG))) {
  1800. zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
  1801. if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
  1802. info->type |= MAY_BE_PACKED_GUARD;
  1803. info->type &= ~MAY_BE_ARRAY_PACKED;
  1804. }
  1805. }
  1806. break;
  1807. case ZEND_SEND_VAL_EX:
  1808. case ZEND_SEND_VAR_EX:
  1809. case ZEND_SEND_VAR_NO_REF_EX:
  1810. if (opline->op2_type == IS_CONST) {
  1811. /* Named parameters not supported in JIT */
  1812. break;
  1813. }
  1814. if (opline->op2.num > MAX_ARG_FLAG_NUM) {
  1815. goto propagate_arg;
  1816. }
  1817. ZEND_FALLTHROUGH;
  1818. case ZEND_SEND_VAL:
  1819. case ZEND_SEND_VAR:
  1820. case ZEND_SEND_VAR_NO_REF:
  1821. case ZEND_SEND_FUNC_ARG:
  1822. if (opline->op2_type == IS_CONST) {
  1823. /* Named parameters not supported in JIT */
  1824. break;
  1825. }
  1826. ADD_OP1_TRACE_GUARD();
  1827. propagate_arg:
  1828. /* Propagate argument type */
  1829. if (frame->call
  1830. && frame->call->func
  1831. && frame->call->func->type == ZEND_USER_FUNCTION
  1832. && opline->op2.num <= frame->call->func->op_array.num_args) {
  1833. uint32_t info;
  1834. if (opline->op1_type == IS_CONST) {
  1835. info = _const_op_type(RT_CONSTANT(opline, opline->op1));
  1836. } else {
  1837. ZEND_ASSERT(ssa_ops[idx].op1_use >= 0);
  1838. info = ssa_var_info[ssa_ops[idx].op1_use].type & ~MAY_BE_GUARD;
  1839. }
  1840. if (frame->call->func->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
  1841. zend_arg_info *arg_info;
  1842. ZEND_ASSERT(frame->call->func->op_array.arg_info);
  1843. arg_info = &frame->call->func->op_array.arg_info[opline->op2.num - 1];
  1844. if (ZEND_TYPE_IS_SET(arg_info->type)) {
  1845. zend_class_entry *ce;
  1846. uint32_t tmp = zend_fetch_arg_info_type(script, arg_info, &ce);
  1847. info &= tmp;
  1848. if (!info) {
  1849. break;
  1850. }
  1851. }
  1852. }
  1853. if (opline->op1_type == IS_CV && (info & MAY_BE_RC1)) {
  1854. info |= MAY_BE_RCN;
  1855. }
  1856. if (info & MAY_BE_UNDEF) {
  1857. info |= MAY_BE_NULL;
  1858. info &= ~MAY_BE_UNDEF;
  1859. }
  1860. if (ARG_SHOULD_BE_SENT_BY_REF(frame->call->func, opline->op2.num)) {
  1861. info |= MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY;
  1862. }
  1863. SET_STACK_INFO(frame->call->stack, opline->op2.num - 1, info);
  1864. }
  1865. break;
  1866. case ZEND_RETURN:
  1867. ADD_OP1_TRACE_GUARD();
  1868. /* Propagate return value types */
  1869. if (opline->op1_type == IS_UNUSED) {
  1870. return_value_info.type = MAY_BE_NULL;
  1871. } else if (opline->op1_type == IS_CONST) {
  1872. return_value_info.type = _const_op_type(RT_CONSTANT(opline, opline->op1));
  1873. } else {
  1874. ZEND_ASSERT(ssa_ops[idx].op1_use >= 0);
  1875. return_value_info = ssa_var_info[ssa_ops[idx].op1_use];
  1876. if (return_value_info.type & MAY_BE_UNDEF) {
  1877. return_value_info.type &= ~MAY_BE_UNDEF;
  1878. return_value_info.type |= MAY_BE_NULL;
  1879. }
  1880. if (return_value_info.type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  1881. /* CVs are going to be destructed and the reference-counter
  1882. of return value may be decremented to 1 */
  1883. return_value_info.type |= MAY_BE_RC1;
  1884. }
  1885. return_value_info.type &= ~MAY_BE_GUARD;
  1886. }
  1887. break;
  1888. case ZEND_CHECK_FUNC_ARG:
  1889. if (!frame
  1890. || !frame->call
  1891. || !frame->call->func) {
  1892. break;
  1893. }
  1894. if (opline->op2_type == IS_CONST
  1895. || opline->op2.num > MAX_ARG_FLAG_NUM) {
  1896. /* Named parameters not supported in JIT */
  1897. TRACE_FRAME_SET_LAST_SEND_UNKNOWN(frame->call);
  1898. break;
  1899. }
  1900. if (ARG_SHOULD_BE_SENT_BY_REF(frame->call->func, opline->op2.num)) {
  1901. TRACE_FRAME_SET_LAST_SEND_BY_REF(frame->call);
  1902. } else {
  1903. TRACE_FRAME_SET_LAST_SEND_BY_VAL(frame->call);
  1904. }
  1905. break;
  1906. case ZEND_FETCH_OBJ_FUNC_ARG:
  1907. if (!frame
  1908. || !frame->call
  1909. || !frame->call->func
  1910. || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(frame->call)) {
  1911. break;
  1912. }
  1913. ZEND_FALLTHROUGH;
  1914. case ZEND_FETCH_OBJ_R:
  1915. case ZEND_FETCH_OBJ_IS:
  1916. case ZEND_FETCH_OBJ_W:
  1917. if (opline->op2_type != IS_CONST
  1918. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  1919. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  1920. break;
  1921. }
  1922. if (opline->op1_type != IS_UNUSED && op1_type == IS_OBJECT) {
  1923. ADD_OP1_TRACE_GUARD();
  1924. }
  1925. break;
  1926. case ZEND_INIT_METHOD_CALL:
  1927. if (opline->op2_type != IS_CONST
  1928. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING) {
  1929. break;
  1930. }
  1931. ADD_OP1_TRACE_GUARD();
  1932. break;
  1933. case ZEND_INIT_DYNAMIC_CALL:
  1934. if (orig_op2_type == IS_OBJECT && op2_ce == zend_ce_closure) {
  1935. ADD_OP2_TRACE_GUARD();
  1936. }
  1937. break;
  1938. case ZEND_SEND_ARRAY:
  1939. case ZEND_SEND_UNPACK:
  1940. case ZEND_CHECK_UNDEF_ARGS:
  1941. case ZEND_INCLUDE_OR_EVAL:
  1942. max_used_stack = used_stack = -1;
  1943. break;
  1944. case ZEND_TYPE_CHECK:
  1945. if (opline->extended_value == MAY_BE_RESOURCE) {
  1946. // TODO: support for is_resource() ???
  1947. break;
  1948. }
  1949. if (op1_type != IS_UNKNOWN
  1950. && (opline->extended_value == (1 << op1_type)
  1951. || opline->extended_value == MAY_BE_ANY - (1 << op1_type))) {
  1952. /* add guards only for exact checks, to avoid code duplication */
  1953. ADD_OP1_TRACE_GUARD();
  1954. }
  1955. break;
  1956. case ZEND_ROPE_INIT:
  1957. case ZEND_ROPE_ADD:
  1958. case ZEND_ROPE_END:
  1959. if (op2_type == IS_STRING) {
  1960. ADD_OP2_TRACE_GUARD();
  1961. }
  1962. break;
  1963. default:
  1964. break;
  1965. }
  1966. len = zend_jit_trace_op_len(opline);
  1967. if (ssa->var_info) {
  1968. /* Add statically inferred ranges */
  1969. if (ssa_ops[idx].op1_def >= 0) {
  1970. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op1_def);
  1971. }
  1972. if (ssa_ops[idx].op2_def >= 0) {
  1973. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op2_def);
  1974. }
  1975. if (ssa_ops[idx].result_def >= 0) {
  1976. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].result_def);
  1977. }
  1978. if (len == 2 && (opline+1)->opcode == ZEND_OP_DATA) {
  1979. if (ssa_ops[idx+1].op1_def >= 0) {
  1980. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx+1].op1_def);
  1981. }
  1982. if (ssa_ops[idx+1].op2_def >= 0) {
  1983. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx+1].op2_def);
  1984. }
  1985. if (ssa_ops[idx+1].result_def >= 0) {
  1986. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx+1].result_def);
  1987. }
  1988. }
  1989. } else {
  1990. if (ssa_ops[idx].op1_def >= 0) {
  1991. ssa_vars[ssa_ops[idx].op1_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM(opline->op1.var));
  1992. if (ssa_ops[idx].op1_use < 0 || !(ssa_var_info[ssa_ops[idx].op1_use].type & MAY_BE_REF)) {
  1993. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx].op1_def);
  1994. }
  1995. }
  1996. if (ssa_ops[idx].op2_def >= 0) {
  1997. ssa_vars[ssa_ops[idx].op2_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM(opline->op2.var));
  1998. if (ssa_ops[idx].op2_use < 0 || !(ssa_var_info[ssa_ops[idx].op2_use].type & MAY_BE_REF)) {
  1999. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx].op2_def);
  2000. }
  2001. }
  2002. if (ssa_ops[idx].result_def >= 0) {
  2003. ssa_vars[ssa_ops[idx].result_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM(opline->result.var));
  2004. if (ssa_ops[idx].result_use < 0 || !(ssa_var_info[ssa_ops[idx].result_use].type & MAY_BE_REF)) {
  2005. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx].result_def);
  2006. }
  2007. }
  2008. if (len == 2 && (opline+1)->opcode == ZEND_OP_DATA) {
  2009. if (ssa_ops[idx+1].op1_def >= 0) {
  2010. ssa_vars[ssa_ops[idx+1].op1_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM((opline+1)->op1.var));
  2011. if (ssa_ops[idx+1].op1_use < 0 || !(ssa_var_info[ssa_ops[idx+1].op1_use].type & MAY_BE_REF)) {
  2012. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx+1].op1_def);
  2013. }
  2014. }
  2015. if (ssa_ops[idx+1].op2_def >= 0) {
  2016. ssa_vars[ssa_ops[idx+1].op2_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM((opline+1)->op2.var));
  2017. if (ssa_ops[idx+1].op2_use < 0 || !(ssa_var_info[ssa_ops[idx+1].op2_use].type & MAY_BE_REF)) {
  2018. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx+1].op2_def);
  2019. }
  2020. }
  2021. if (ssa_ops[idx+1].result_def >= 0) {
  2022. ssa_vars[ssa_ops[idx+1].result_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM((opline+1)->result.var));
  2023. if (ssa_ops[idx+1].result_use < 0 || !(ssa_var_info[ssa_ops[idx+1].result_use].type & MAY_BE_REF)) {
  2024. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx+1].result_def);
  2025. }
  2026. }
  2027. }
  2028. }
  2029. if (opline->opcode == ZEND_RECV_INIT
  2030. && !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  2031. /* RECV_INIT always copy the constant */
  2032. ssa_var_info[ssa_ops[idx].result_def].type = _const_op_type(RT_CONSTANT(opline, opline->op2));
  2033. } else if ((opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW)
  2034. && ssa_opcodes[idx + 1] == ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value)) {
  2035. if (ssa_ops[idx].op2_use >= 0 && ssa_ops[idx].op2_def >= 0) {
  2036. ssa_var_info[ssa_ops[idx].op2_def] = ssa_var_info[ssa_ops[idx].op2_use];
  2037. }
  2038. } else {
  2039. if (zend_update_type_info(op_array, tssa, script, (zend_op*)opline, ssa_ops + idx, ssa_opcodes, optimization_level) == FAILURE) {
  2040. // TODO:
  2041. assert(0);
  2042. }
  2043. if (opline->opcode == ZEND_ASSIGN_DIM_OP
  2044. && ssa_ops[idx].op1_def > 0
  2045. && op1_type == IS_ARRAY
  2046. && (orig_op1_type & IS_TRACE_PACKED)
  2047. && val_type != IS_UNKNOWN
  2048. && val_type != IS_UNDEF
  2049. && ((opline->op2_type == IS_CONST
  2050. && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
  2051. || (opline->op2_type != IS_CONST
  2052. && op2_type == IS_LONG))) {
  2053. zend_ssa_var_info *info = &ssa_var_info[ssa_ops[idx].op1_def];
  2054. info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
  2055. }
  2056. }
  2057. if (ssa->var_info) {
  2058. /* Add statically inferred restrictions */
  2059. if (ssa_ops[idx].op1_def >= 0) {
  2060. if (opline->opcode == ZEND_SEND_VAR_EX
  2061. && frame
  2062. && frame->call
  2063. && frame->call->func
  2064. && !ARG_SHOULD_BE_SENT_BY_REF(frame->call->func, opline->op2.num)) {
  2065. ssa_var_info[ssa_ops[idx].op1_def] = ssa_var_info[ssa_ops[idx].op1_use];
  2066. ssa_var_info[ssa_ops[idx].op1_def].type &= ~MAY_BE_GUARD;
  2067. if (ssa_var_info[ssa_ops[idx].op1_def].type & MAY_BE_RC1) {
  2068. ssa_var_info[ssa_ops[idx].op1_def].type |= MAY_BE_RCN;
  2069. }
  2070. } else {
  2071. zend_jit_trace_restrict_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op1_def);
  2072. }
  2073. }
  2074. if (ssa_ops[idx].op2_def >= 0) {
  2075. if ((opline->opcode != ZEND_FE_FETCH_R && opline->opcode != ZEND_FE_FETCH_RW)
  2076. || ssa_opcodes[idx + 1] != ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value)) {
  2077. zend_jit_trace_restrict_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op2_def);
  2078. }
  2079. }
  2080. if (ssa_ops[idx].result_def >= 0) {
  2081. zend_jit_trace_restrict_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].result_def);
  2082. }
  2083. }
  2084. idx++;
  2085. while (len > 1) {
  2086. opline++;
  2087. if (opline->opcode != ZEND_OP_DATA) {
  2088. if (ssa->var_info) {
  2089. /* Add statically inferred ranges */
  2090. if (ssa_ops[idx].op1_def >= 0) {
  2091. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op1_def);
  2092. }
  2093. if (ssa_ops[idx].op2_def >= 0) {
  2094. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op2_def);
  2095. }
  2096. if (ssa_ops[idx].result_def >= 0) {
  2097. zend_jit_trace_copy_ssa_var_range(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].result_def);
  2098. }
  2099. } else {
  2100. if (ssa_ops[idx].op1_def >= 0) {
  2101. ssa_vars[ssa_ops[idx].op1_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM(opline->op1.var));
  2102. if (ssa_ops[idx].op1_use < 0 || !(ssa_var_info[ssa_ops[idx].op1_use].type & MAY_BE_REF)) {
  2103. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx].op1_def);
  2104. }
  2105. }
  2106. if (ssa_ops[idx].op2_def >= 0) {
  2107. ssa_vars[ssa_ops[idx].op2_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM(opline->op2.var));
  2108. if (ssa_ops[idx].op2_use < 0 || !(ssa_var_info[ssa_ops[idx].op2_use].type & MAY_BE_REF)) {
  2109. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx].op2_def);
  2110. }
  2111. }
  2112. if (ssa_ops[idx].result_def >= 0) {
  2113. ssa_vars[ssa_ops[idx].result_def].alias = zend_jit_var_may_alias(op_array, ssa, EX_VAR_TO_NUM(opline->result.var));
  2114. if (ssa_ops[idx].result_use < 0 || !(ssa_var_info[ssa_ops[idx].result_use].type & MAY_BE_REF)) {
  2115. zend_jit_trace_propagate_range(op_array, ssa_opcodes, tssa, ssa_ops[idx].result_def);
  2116. }
  2117. }
  2118. }
  2119. if (opline->opcode == ZEND_RECV_INIT
  2120. && !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  2121. /* RECV_INIT always copy the constant */
  2122. ssa_var_info[ssa_ops[idx].result_def].type = _const_op_type(RT_CONSTANT(opline, opline->op2));
  2123. } else {
  2124. if (zend_update_type_info(op_array, tssa, script, (zend_op*)opline, ssa_ops + idx, ssa_opcodes, optimization_level) == FAILURE) {
  2125. // TODO:
  2126. assert(0);
  2127. }
  2128. }
  2129. }
  2130. if (ssa->var_info) {
  2131. /* Add statically inferred restrictions */
  2132. if (ssa_ops[idx].op1_def >= 0) {
  2133. zend_jit_trace_restrict_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op1_def);
  2134. }
  2135. if (ssa_ops[idx].op2_def >= 0) {
  2136. zend_jit_trace_restrict_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].op2_def);
  2137. }
  2138. if (ssa_ops[idx].result_def >= 0) {
  2139. zend_jit_trace_restrict_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, ssa_ops[idx].result_def);
  2140. }
  2141. }
  2142. idx++;
  2143. len--;
  2144. }
  2145. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  2146. op_array = p->op_array;
  2147. jit_extension =
  2148. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  2149. ssa = &jit_extension->func_info.ssa;
  2150. call = frame->call;
  2151. if (!call) {
  2152. /* Trace missed INIT_FCALL opcode */
  2153. call = top;
  2154. TRACE_FRAME_INIT(call, op_array, 0, 0);
  2155. call->used_stack = 0;
  2156. top = zend_jit_trace_call_frame(top, op_array);
  2157. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  2158. SET_STACK_TYPE(call->stack, i, IS_UNKNOWN, 1);
  2159. }
  2160. } else {
  2161. ZEND_ASSERT(&call->func->op_array == op_array);
  2162. }
  2163. frame->call = call->prev;
  2164. call->prev = frame;
  2165. TRACE_FRAME_SET_RETURN_SSA_VAR(call, find_return_ssa_var(p - 1, ssa_ops + (idx - 1)));
  2166. frame = call;
  2167. level++;
  2168. i = 0;
  2169. v = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  2170. while (i < op_array->last_var) {
  2171. ssa_vars[v].var = i;
  2172. if (i < op_array->num_args) {
  2173. if (ssa->var_info
  2174. && zend_jit_trace_copy_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, v)) {
  2175. /* pass */
  2176. } else {
  2177. ssa_vars[v].alias = zend_jit_var_may_alias(op_array, ssa, i);
  2178. if (op_array->arg_info) {
  2179. zend_arg_info *arg_info = &op_array->arg_info[i];
  2180. zend_class_entry *ce;
  2181. uint32_t tmp = zend_fetch_arg_info_type(script, arg_info, &ce);
  2182. if (ZEND_ARG_SEND_MODE(arg_info)) {
  2183. tmp |= MAY_BE_REF;
  2184. }
  2185. ssa_var_info[v].type = tmp;
  2186. ssa_var_info[v].ce = ce;
  2187. ssa_var_info[v].is_instanceof = 1;
  2188. } else {
  2189. ssa_var_info[v].type = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2190. }
  2191. }
  2192. } else {
  2193. if (ssa->vars) {
  2194. ssa_vars[v].no_val = ssa->vars[i].no_val;
  2195. ssa_vars[v].alias = ssa->vars[i].alias;
  2196. } else {
  2197. ssa_vars[v].alias = zend_jit_var_may_alias(op_array, ssa, i);
  2198. }
  2199. if (ssa_vars[v].alias == NO_ALIAS) {
  2200. ssa_var_info[v].type = MAY_BE_UNDEF;
  2201. } else {
  2202. ssa_var_info[v].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2203. }
  2204. }
  2205. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
  2206. && i < op_array->num_args) {
  2207. /* Propagate argument type */
  2208. ssa_var_info[v].type &= STACK_INFO(frame->stack, i);
  2209. }
  2210. i++;
  2211. v++;
  2212. }
  2213. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  2214. op_array = p->op_array;
  2215. jit_extension =
  2216. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  2217. ssa = &jit_extension->func_info.ssa;
  2218. if (level == 0) {
  2219. i = 0;
  2220. v = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  2221. while (i < op_array->last_var) {
  2222. ssa_vars[v].var = i;
  2223. if (!ssa->var_info
  2224. || !zend_jit_trace_copy_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, v)) {
  2225. ssa_var_info[v].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2226. }
  2227. i++;
  2228. v++;
  2229. }
  2230. while (i < op_array->last_var + op_array->T) {
  2231. ssa_vars[v].var = i;
  2232. if (!ssa->var_info
  2233. || !zend_jit_trace_copy_ssa_var_info(op_array, ssa, ssa_opcodes, tssa, v)) {
  2234. ssa_var_info[v].type = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2235. }
  2236. i++;
  2237. v++;
  2238. }
  2239. if (return_value_info.type != 0) {
  2240. zend_jit_trace_rec *q = p + 1;
  2241. while (q->op == ZEND_JIT_TRACE_INIT_CALL) {
  2242. q++;
  2243. }
  2244. if (q->op == ZEND_JIT_TRACE_VM
  2245. || (q->op == ZEND_JIT_TRACE_END
  2246. && q->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET)) {
  2247. const zend_op *opline = q->opline - 1;
  2248. if (opline->result_type != IS_UNUSED) {
  2249. ssa_var_info[
  2250. ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info) +
  2251. EX_VAR_TO_NUM(opline->result.var)] = return_value_info;
  2252. }
  2253. }
  2254. memset(&return_value_info, 0, sizeof(return_value_info));
  2255. }
  2256. } else {
  2257. level--;
  2258. if (return_value_info.type != 0) {
  2259. if ((p+1)->op == ZEND_JIT_TRACE_VM) {
  2260. const zend_op *opline = (p+1)->opline - 1;
  2261. if (opline->result_type != IS_UNUSED) {
  2262. if (TRACE_FRAME_RETURN_SSA_VAR(frame) >= 0) {
  2263. ssa_var_info[TRACE_FRAME_RETURN_SSA_VAR(frame)] = return_value_info;
  2264. }
  2265. }
  2266. }
  2267. memset(&return_value_info, 0, sizeof(return_value_info));
  2268. }
  2269. }
  2270. top = frame;
  2271. if (frame->prev) {
  2272. if (used_stack > 0) {
  2273. used_stack -= frame->used_stack;
  2274. }
  2275. frame = frame->prev;
  2276. ZEND_ASSERT(&frame->func->op_array == op_array);
  2277. } else {
  2278. max_used_stack = used_stack = -1;
  2279. frame = zend_jit_trace_ret_frame(frame, op_array);
  2280. TRACE_FRAME_INIT(frame, op_array, 0, 0);
  2281. TRACE_FRAME_SET_RETURN_SSA_VAR(frame, -1);
  2282. frame->used_stack = 0;
  2283. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  2284. SET_STACK_TYPE(frame->stack, i, IS_UNKNOWN, 1);
  2285. }
  2286. }
  2287. } else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
  2288. call = top;
  2289. TRACE_FRAME_INIT(call, p->func, 0, 0);
  2290. call->prev = frame->call;
  2291. call->used_stack = 0;
  2292. frame->call = call;
  2293. top = zend_jit_trace_call_frame(top, p->op_array);
  2294. if (p->func && p->func->type == ZEND_USER_FUNCTION) {
  2295. for (i = 0; i < p->op_array->last_var + p->op_array->T; i++) {
  2296. SET_STACK_INFO(call->stack, i, -1);
  2297. }
  2298. }
  2299. if (used_stack >= 0
  2300. && !(p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL)) {
  2301. if (p->func == NULL || (p-1)->op != ZEND_JIT_TRACE_VM) {
  2302. max_used_stack = used_stack = -1;
  2303. } else {
  2304. const zend_op *opline = (p-1)->opline;
  2305. switch (opline->opcode) {
  2306. case ZEND_INIT_FCALL:
  2307. case ZEND_INIT_FCALL_BY_NAME:
  2308. case ZEND_INIT_NS_FCALL_BY_NAME:
  2309. case ZEND_INIT_METHOD_CALL:
  2310. case ZEND_INIT_DYNAMIC_CALL:
  2311. //case ZEND_INIT_STATIC_METHOD_CALL:
  2312. //case ZEND_INIT_USER_CALL:
  2313. //case ZEND_NEW:
  2314. frame->used_stack = zend_vm_calc_used_stack(opline->extended_value, (zend_function*)p->func);
  2315. used_stack += frame->used_stack;
  2316. if (used_stack > max_used_stack) {
  2317. max_used_stack = used_stack;
  2318. }
  2319. break;
  2320. default:
  2321. max_used_stack = used_stack = -1;
  2322. }
  2323. }
  2324. }
  2325. } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
  2326. call = frame->call;
  2327. if (call) {
  2328. top = call;
  2329. frame->call = call->prev;
  2330. }
  2331. if (idx > 0
  2332. && ssa_ops[idx-1].result_def >= 0
  2333. && (p->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)
  2334. && !(p->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
  2335. ZEND_ASSERT(ssa_opcodes[idx-1] == opline);
  2336. ZEND_ASSERT(opline->opcode == ZEND_DO_ICALL ||
  2337. opline->opcode == ZEND_DO_FCALL ||
  2338. opline->opcode == ZEND_DO_FCALL_BY_NAME);
  2339. if (opline->result_type != IS_UNDEF) {
  2340. zend_class_entry *ce;
  2341. const zend_function *func = p->func;
  2342. zend_arg_info *ret_info = func->common.arg_info - 1;
  2343. uint32_t ret_type = zend_fetch_arg_info_type(NULL, ret_info, &ce);
  2344. ssa_var_info[ssa_ops[idx-1].result_def].type &= ret_type;
  2345. }
  2346. }
  2347. } else if (p->op == ZEND_JIT_TRACE_END) {
  2348. break;
  2349. }
  2350. }
  2351. ((zend_tssa*)tssa)->used_stack = max_used_stack;
  2352. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  2353. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  2354. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  2355. /* Propagate guards through Phi sources */
  2356. zend_ssa_phi *phi = tssa->blocks[1].phis;
  2357. op_array = trace_buffer->op_array;
  2358. jit_extension =
  2359. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  2360. ssa = &jit_extension->func_info.ssa;
  2361. while (phi) {
  2362. uint32_t t = ssa_var_info[phi->ssa_var].type;
  2363. if ((t & MAY_BE_GUARD) && tssa->vars[phi->ssa_var].alias == NO_ALIAS) {
  2364. uint32_t t0 = ssa_var_info[phi->sources[0]].type;
  2365. uint32_t t1 = ssa_var_info[phi->sources[1]].type;
  2366. if (((t0 | t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
  2367. if (!((t0 | t1) & MAY_BE_GUARD)) {
  2368. ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
  2369. }
  2370. } else if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
  2371. if (!(t1 & MAY_BE_GUARD)
  2372. || is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
  2373. ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
  2374. t0 = (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
  2375. (t0 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
  2376. MAY_BE_GUARD;
  2377. if (!(t0 & MAY_BE_ARRAY)) {
  2378. t0 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
  2379. }
  2380. if (!(t0 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
  2381. t0 &= ~(MAY_BE_RC1|MAY_BE_RCN);
  2382. }
  2383. ssa_var_info[phi->sources[0]].type = t0;
  2384. ssa_var_info[phi->sources[0]].type = t0;
  2385. }
  2386. } else {
  2387. if ((t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
  2388. t0 = (t & t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
  2389. (t0 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
  2390. MAY_BE_GUARD;
  2391. if (!(t0 & MAY_BE_ARRAY)) {
  2392. t0 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
  2393. }
  2394. if (!(t0 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
  2395. t0 &= ~(MAY_BE_RC1|MAY_BE_RCN);
  2396. }
  2397. ssa_var_info[phi->sources[0]].type = t0;
  2398. }
  2399. if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
  2400. if (((t & t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != 0
  2401. && is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
  2402. t1 = (t & t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
  2403. (t1 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
  2404. MAY_BE_GUARD;
  2405. if (!(t1 & MAY_BE_ARRAY)) {
  2406. t1 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
  2407. }
  2408. if (!(t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
  2409. t1 &= ~(MAY_BE_RC1|MAY_BE_RCN);
  2410. }
  2411. ssa_var_info[phi->sources[1]].type = t1;
  2412. ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
  2413. }
  2414. }
  2415. }
  2416. t = ssa_var_info[phi->ssa_var].type;
  2417. }
  2418. if ((t & MAY_BE_PACKED_GUARD) && tssa->vars[phi->ssa_var].alias == NO_ALIAS) {
  2419. uint32_t t0 = ssa_var_info[phi->sources[0]].type;
  2420. uint32_t t1 = ssa_var_info[phi->sources[1]].type;
  2421. if (((t0 | t1) & MAY_BE_ARRAY_KEY_ANY) == (t & MAY_BE_ARRAY_KEY_ANY)) {
  2422. if (!((t0 | t1) & MAY_BE_PACKED_GUARD)) {
  2423. ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_PACKED_GUARD;
  2424. }
  2425. } else if ((t1 & MAY_BE_ARRAY_KEY_ANY) == (t & MAY_BE_ARRAY_KEY_ANY)) {
  2426. if (!(t1 & MAY_BE_PACKED_GUARD)) {
  2427. ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_PACKED_GUARD;
  2428. ssa_var_info[phi->sources[0]].type =
  2429. (t0 & ~MAY_BE_ARRAY_KEY_ANY) | (t & MAY_BE_ARRAY_KEY_ANY) | MAY_BE_PACKED_GUARD;
  2430. }
  2431. }
  2432. }
  2433. phi = phi->next;
  2434. }
  2435. }
  2436. if (UNEXPECTED(JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_TSSA)) {
  2437. if (parent_trace) {
  2438. fprintf(stderr, "---- TRACE %d TSSA start (side trace %d/%d) %s%s%s() %s:%d\n",
  2439. ZEND_JIT_TRACE_NUM,
  2440. parent_trace,
  2441. exit_num,
  2442. trace_buffer->op_array->scope ? ZSTR_VAL(trace_buffer->op_array->scope->name) : "",
  2443. trace_buffer->op_array->scope ? "::" : "",
  2444. trace_buffer->op_array->function_name ?
  2445. ZSTR_VAL(trace_buffer->op_array->function_name) : "$main",
  2446. ZSTR_VAL(trace_buffer->op_array->filename),
  2447. trace_buffer[1].opline->lineno);
  2448. } else {
  2449. fprintf(stderr, "---- TRACE %d TSSA start (%s) %s%s%s() %s:%d\n",
  2450. ZEND_JIT_TRACE_NUM,
  2451. zend_jit_trace_star_desc(trace_buffer->start),
  2452. trace_buffer->op_array->scope ? ZSTR_VAL(trace_buffer->op_array->scope->name) : "",
  2453. trace_buffer->op_array->scope ? "::" : "",
  2454. trace_buffer->op_array->function_name ?
  2455. ZSTR_VAL(trace_buffer->op_array->function_name) : "$main",
  2456. ZSTR_VAL(trace_buffer->op_array->filename),
  2457. trace_buffer[1].opline->lineno);
  2458. }
  2459. zend_jit_dump_trace(trace_buffer, tssa);
  2460. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LINK) {
  2461. uint32_t idx = trace_buffer[1].last;
  2462. uint32_t link_to = zend_jit_find_trace(trace_buffer[idx].opline->handler);
  2463. fprintf(stderr, "---- TRACE %d TSSA stop (link to %d)\n",
  2464. ZEND_JIT_TRACE_NUM,
  2465. link_to);
  2466. } else {
  2467. fprintf(stderr, "---- TRACE %d TSSA stop (%s)\n",
  2468. ZEND_JIT_TRACE_NUM,
  2469. zend_jit_trace_stop_description[trace_buffer->stop]);
  2470. }
  2471. }
  2472. return tssa;
  2473. }
  2474. static void zend_jit_close_var(zend_jit_trace_stack *stack, uint32_t n, int *start, int *end, uint8_t *flags, int line)
  2475. {
  2476. int32_t var = STACK_VAR(stack, n);
  2477. if (var >= 0 && start[var] >= 0 && !(flags[var] & ZREG_LAST_USE)) {
  2478. // TODO: shrink interval to last side exit ????
  2479. end[var] = line;
  2480. }
  2481. }
  2482. static void zend_jit_trace_use_var(int line, int var, int def, int use_chain, int *start, int *end, uint8_t *flags, const zend_ssa *ssa, const zend_op **ssa_opcodes, const zend_op_array *op_array, const zend_ssa *op_array_ssa)
  2483. {
  2484. ZEND_ASSERT(start[var] >= 0);
  2485. ZEND_ASSERT(!(flags[var] & ZREG_LAST_USE));
  2486. end[var] = line;
  2487. if (def >= 0) {
  2488. flags[var] |= ZREG_LAST_USE;
  2489. } else if (use_chain < 0 && (flags[var] & (ZREG_LOAD|ZREG_STORE))) {
  2490. flags[var] |= ZREG_LAST_USE;
  2491. } else if (use_chain >= 0 && !zend_ssa_is_no_val_use(ssa_opcodes[use_chain], ssa->ops + use_chain, var)) {
  2492. /* pass */
  2493. } else if (op_array_ssa->vars) {
  2494. uint32_t use = ssa_opcodes[line] - op_array->opcodes;
  2495. if (ssa->ops[line].op1_use == var) {
  2496. if (zend_ssa_is_last_use(op_array, op_array_ssa, op_array_ssa->ops[use].op1_use, use)) {
  2497. flags[var] |= ZREG_LAST_USE;
  2498. }
  2499. } else if (ssa->ops[line].op2_use == var) {
  2500. if (zend_ssa_is_last_use(op_array, op_array_ssa, op_array_ssa->ops[use].op2_use, use)) {
  2501. flags[var] |= ZREG_LAST_USE;
  2502. }
  2503. } else if (ssa->ops[line].result_use == var) {
  2504. if (zend_ssa_is_last_use(op_array, op_array_ssa, op_array_ssa->ops[use].result_use, use)) {
  2505. flags[var] |= ZREG_LAST_USE;
  2506. }
  2507. }
  2508. }
  2509. }
  2510. static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace_rec *trace_buffer, zend_ssa *ssa, uint32_t parent_trace, uint32_t exit_num)
  2511. {
  2512. const zend_op **ssa_opcodes = ((zend_tssa*)ssa)->tssa_opcodes;
  2513. zend_jit_trace_rec *p;
  2514. const zend_op_array *op_array;
  2515. zend_jit_op_array_trace_extension *jit_extension;
  2516. const zend_ssa *op_array_ssa;
  2517. const zend_ssa_op *ssa_op;
  2518. int i, j, idx, count, level;
  2519. int last_idx = -1;
  2520. int *start, *end;
  2521. uint8_t *flags;
  2522. const zend_op_array **vars_op_array;
  2523. zend_lifetime_interval **intervals, *list, *ival;
  2524. void *checkpoint;
  2525. zend_jit_trace_stack_frame *frame;
  2526. zend_jit_trace_stack *stack;
  2527. uint32_t parent_vars_count = parent_trace ?
  2528. zend_jit_traces[parent_trace].exit_info[exit_num].stack_size : 0;
  2529. zend_jit_trace_stack *parent_stack = parent_trace ?
  2530. zend_jit_traces[parent_trace].stack_map +
  2531. zend_jit_traces[parent_trace].exit_info[exit_num].stack_offset : NULL;
  2532. ALLOCA_FLAG(use_heap);
  2533. ZEND_ASSERT(ssa->var_info != NULL);
  2534. start = do_alloca(sizeof(int) * ssa->vars_count * 2 +
  2535. ZEND_MM_ALIGNED_SIZE(sizeof(uint8_t) * ssa->vars_count) +
  2536. ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array*) * ssa->vars_count),
  2537. use_heap);
  2538. if (!start) {
  2539. return NULL;
  2540. }
  2541. end = start + ssa->vars_count;
  2542. flags = (uint8_t*)(end + ssa->vars_count);
  2543. vars_op_array = (const zend_op_array**)(flags + ZEND_MM_ALIGNED_SIZE(sizeof(uint8_t) * ssa->vars_count));
  2544. memset(start, -1, sizeof(int) * ssa->vars_count * 2);
  2545. memset(flags, 0, sizeof(uint8_t) * ssa->vars_count);
  2546. memset(ZEND_VOIDP(vars_op_array), 0, sizeof(zend_op_array*) * ssa->vars_count);
  2547. op_array = trace_buffer->op_array;
  2548. jit_extension =
  2549. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  2550. op_array_ssa = &jit_extension->func_info.ssa;
  2551. frame = JIT_G(current_frame);
  2552. frame->prev = NULL;
  2553. frame->func = (const zend_function*)op_array;
  2554. stack = frame->stack;
  2555. count = 0;
  2556. i = 0;
  2557. j = op_array->last_var;
  2558. if (trace_buffer->start != ZEND_JIT_TRACE_START_ENTER) {
  2559. j += op_array->T;
  2560. }
  2561. while (i < j) {
  2562. SET_STACK_VAR(stack, i, i);
  2563. vars_op_array[i] = op_array;
  2564. /* We don't start intervals for variables used in Phi */
  2565. if ((ssa->vars[i].use_chain >= 0 /*|| ssa->vars[i].phi_use_chain*/)
  2566. && !zend_ssa_is_no_val_use(ssa_opcodes[ssa->vars[i].use_chain], ssa->ops + ssa->vars[i].use_chain, i)
  2567. && ssa->vars[i].alias == NO_ALIAS
  2568. && zend_jit_var_supports_reg(ssa, i)) {
  2569. start[i] = 0;
  2570. if (i < parent_vars_count
  2571. && STACK_REG(parent_stack, i) != ZREG_NONE
  2572. && STACK_REG(parent_stack, i) < ZREG_NUM) {
  2573. /* We will try to reuse register from parent trace */
  2574. flags[i] = STACK_FLAGS(parent_stack, i);
  2575. count += 2;
  2576. } else {
  2577. flags[i] = ZREG_LOAD;
  2578. count++;
  2579. }
  2580. }
  2581. i++;
  2582. }
  2583. if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
  2584. j = op_array->last_var + op_array->T;
  2585. while (i < j) {
  2586. SET_STACK_VAR(stack, i, -1);
  2587. i++;
  2588. }
  2589. }
  2590. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  2591. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  2592. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  2593. zend_ssa_phi *phi = ssa->blocks[1].phis;
  2594. while (phi) {
  2595. SET_STACK_VAR(stack, phi->var, phi->ssa_var);
  2596. vars_op_array[phi->ssa_var] = op_array;
  2597. if (ssa->vars[phi->ssa_var].use_chain >= 0
  2598. && ssa->vars[phi->ssa_var].alias == NO_ALIAS
  2599. && zend_jit_var_supports_reg(ssa, phi->ssa_var)) {
  2600. start[phi->ssa_var] = 0;
  2601. count++;
  2602. }
  2603. phi = phi->next;
  2604. }
  2605. }
  2606. p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
  2607. level = 0;
  2608. ssa_op = ssa->ops;
  2609. idx = 0;
  2610. for (;;p++) {
  2611. if (p->op == ZEND_JIT_TRACE_VM) {
  2612. const zend_op *opline = p->opline;
  2613. int len;
  2614. bool support_opline;
  2615. support_opline =
  2616. zend_jit_opline_supports_reg(op_array, ssa, opline, ssa_op, p);
  2617. if (support_opline
  2618. && opline->opcode == ZEND_ASSIGN
  2619. && opline->op1_type == IS_CV
  2620. && ssa_op->op1_def >= 0
  2621. && ssa->vars[ssa_op->op1_def].alias != NO_ALIAS) {
  2622. /* avoid register allocation in case of possibility of indirect modification*/
  2623. support_opline = 0;
  2624. }
  2625. if (ssa_op->op1_use >= 0
  2626. && start[ssa_op->op1_use] >= 0
  2627. && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) {
  2628. if (support_opline) {
  2629. zend_jit_trace_use_var(idx, ssa_op->op1_use, ssa_op->op1_def, ssa_op->op1_use_chain, start, end, flags, ssa, ssa_opcodes, op_array, op_array_ssa);
  2630. if (opline->op1_type != IS_CV) {
  2631. if (opline->opcode == ZEND_CASE
  2632. || opline->opcode == ZEND_CASE_STRICT
  2633. || opline->opcode == ZEND_SWITCH_LONG
  2634. || opline->opcode == ZEND_MATCH
  2635. || opline->opcode == ZEND_FETCH_LIST_R
  2636. || opline->opcode == ZEND_COPY_TMP
  2637. || opline->opcode == ZEND_SWITCH_STRING
  2638. || opline->opcode == ZEND_FE_FETCH_R
  2639. || opline->opcode == ZEND_FE_FETCH_RW
  2640. || opline->opcode == ZEND_FETCH_LIST_W
  2641. || opline->opcode == ZEND_VERIFY_RETURN_TYPE
  2642. || opline->opcode == ZEND_BIND_LEXICAL
  2643. || opline->opcode == ZEND_ROPE_ADD) {
  2644. /* The value is kept alive and may be used outside of the trace */
  2645. flags[ssa_op->op1_use] |= ZREG_STORE;
  2646. } else {
  2647. flags[ssa_op->op1_use] |= ZREG_LAST_USE;
  2648. }
  2649. }
  2650. } else {
  2651. start[ssa_op->op1_use] = -1;
  2652. end[ssa_op->op1_use] = -1;
  2653. count--;
  2654. }
  2655. }
  2656. if (ssa_op->op2_use >= 0
  2657. && ssa_op->op2_use != ssa_op->op1_use
  2658. && start[ssa_op->op2_use] >= 0
  2659. && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op2_use)) {
  2660. if (support_opline) {
  2661. zend_jit_trace_use_var(idx, ssa_op->op2_use, ssa_op->op2_def, ssa_op->op2_use_chain, start, end, flags, ssa, ssa_opcodes, op_array, op_array_ssa);
  2662. if (opline->op2_type != IS_CV) {
  2663. flags[ssa_op->op2_use] |= ZREG_LAST_USE;
  2664. }
  2665. } else {
  2666. start[ssa_op->op2_use] = -1;
  2667. end[ssa_op->op2_use] = -1;
  2668. count--;
  2669. }
  2670. }
  2671. if (ssa_op->result_use >= 0
  2672. && ssa_op->result_use != ssa_op->op1_use
  2673. && ssa_op->result_use != ssa_op->op2_use
  2674. && start[ssa_op->result_use] >= 0
  2675. && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->result_use)) {
  2676. if (support_opline) {
  2677. zend_jit_trace_use_var(idx, ssa_op->result_use, ssa_op->result_def, ssa_op->res_use_chain, start, end, flags, ssa, ssa_opcodes, op_array, op_array_ssa);
  2678. } else {
  2679. start[ssa_op->result_use] = -1;
  2680. end[ssa_op->result_use] = -1;
  2681. count--;
  2682. }
  2683. }
  2684. if (ssa_op->op1_def >= 0) {
  2685. zend_jit_close_var(stack, EX_VAR_TO_NUM(opline->op1.var), start, end, flags, idx);
  2686. SET_STACK_VAR(stack, EX_VAR_TO_NUM(opline->op1.var), ssa_op->op1_def);
  2687. }
  2688. if (ssa_op->op2_def >= 0) {
  2689. zend_jit_close_var(stack, EX_VAR_TO_NUM(opline->op2.var), start, end, flags, idx);
  2690. SET_STACK_VAR(stack, EX_VAR_TO_NUM(opline->op2.var), ssa_op->op2_def);
  2691. }
  2692. if (ssa_op->result_def >= 0) {
  2693. zend_jit_close_var(stack, EX_VAR_TO_NUM(opline->result.var), start, end, flags, idx);
  2694. SET_STACK_VAR(stack, EX_VAR_TO_NUM(opline->result.var), ssa_op->result_def);
  2695. }
  2696. if (support_opline) {
  2697. if (ssa_op->result_def >= 0
  2698. && (ssa->vars[ssa_op->result_def].use_chain >= 0
  2699. || ssa->vars[ssa_op->result_def].phi_use_chain)
  2700. && ssa->vars[ssa_op->result_def].alias == NO_ALIAS
  2701. && zend_jit_var_supports_reg(ssa, ssa_op->result_def)) {
  2702. if (!(ssa->var_info[ssa_op->result_def].type & MAY_BE_GUARD)
  2703. || opline->opcode == ZEND_PRE_INC
  2704. || opline->opcode == ZEND_PRE_DEC
  2705. || opline->opcode == ZEND_POST_INC
  2706. || opline->opcode == ZEND_POST_DEC
  2707. || opline->opcode == ZEND_ADD
  2708. || opline->opcode == ZEND_SUB
  2709. || opline->opcode == ZEND_MUL
  2710. || opline->opcode == ZEND_FETCH_DIM_R
  2711. || opline->opcode == ZEND_FETCH_CONSTANT) {
  2712. if (!(ssa->var_info[ssa_op->result_def].type & MAY_BE_DOUBLE)
  2713. || (opline->opcode != ZEND_PRE_INC && opline->opcode != ZEND_PRE_DEC)) {
  2714. start[ssa_op->result_def] = idx;
  2715. vars_op_array[ssa_op->result_def] = op_array;
  2716. count++;
  2717. }
  2718. }
  2719. }
  2720. if (ssa_op->op1_def >= 0
  2721. && (ssa->vars[ssa_op->op1_def].use_chain >= 0
  2722. || ssa->vars[ssa_op->op1_def].phi_use_chain)
  2723. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS
  2724. && zend_jit_var_supports_reg(ssa, ssa_op->op1_def)) {
  2725. start[ssa_op->op1_def] = idx;
  2726. vars_op_array[ssa_op->op1_def] = op_array;
  2727. count++;
  2728. }
  2729. if (ssa_op->op2_def >= 0
  2730. && (ssa->vars[ssa_op->op2_def].use_chain >= 0
  2731. || ssa->vars[ssa_op->op2_def].phi_use_chain)
  2732. && ssa->vars[ssa_op->op2_def].alias == NO_ALIAS
  2733. && zend_jit_var_supports_reg(ssa, ssa_op->op2_def)) {
  2734. start[ssa_op->op2_def] = idx;
  2735. vars_op_array[ssa_op->op2_def] = op_array;
  2736. count++;
  2737. }
  2738. }
  2739. len = zend_jit_trace_op_len(opline);
  2740. switch (opline->opcode) {
  2741. case ZEND_ASSIGN_DIM:
  2742. case ZEND_ASSIGN_OBJ:
  2743. case ZEND_ASSIGN_STATIC_PROP:
  2744. case ZEND_ASSIGN_DIM_OP:
  2745. case ZEND_ASSIGN_OBJ_OP:
  2746. case ZEND_ASSIGN_STATIC_PROP_OP:
  2747. case ZEND_ASSIGN_OBJ_REF:
  2748. case ZEND_ASSIGN_STATIC_PROP_REF:
  2749. /* OP_DATA */
  2750. ssa_op++;
  2751. opline++;
  2752. if (ssa_op->op1_use >= 0
  2753. && start[ssa_op->op1_use] >= 0
  2754. && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) {
  2755. if (support_opline) {
  2756. zend_jit_trace_use_var(idx, ssa_op->op1_use, ssa_op->op1_def, ssa_op->op1_use_chain, start, end, flags, ssa, ssa_opcodes, op_array, op_array_ssa);
  2757. if (opline->op1_type != IS_CV) {
  2758. flags[ssa_op->op1_use] |= ZREG_LAST_USE;
  2759. }
  2760. } else {
  2761. start[ssa_op->op1_use] = -1;
  2762. end[ssa_op->op1_use] = -1;
  2763. count--;
  2764. }
  2765. }
  2766. if (ssa_op->op1_def >= 0) {
  2767. zend_jit_close_var(stack, EX_VAR_TO_NUM(opline->op1.var), start, end, flags, idx);
  2768. SET_STACK_VAR(stack, EX_VAR_TO_NUM(opline->op1.var), ssa_op->op1_def);
  2769. if (support_opline
  2770. && (ssa->vars[ssa_op->op1_def].use_chain >= 0
  2771. || ssa->vars[ssa_op->op1_def].phi_use_chain)
  2772. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS
  2773. && zend_jit_var_supports_reg(ssa, ssa_op->op1_def)) {
  2774. start[ssa_op->op1_def] = idx;
  2775. vars_op_array[ssa_op->op1_def] = op_array;
  2776. count++;
  2777. }
  2778. }
  2779. ssa_op++;
  2780. opline++;
  2781. idx+=2;
  2782. break;
  2783. case ZEND_RECV_INIT:
  2784. ssa_op++;
  2785. opline++;
  2786. idx++;
  2787. while (opline->opcode == ZEND_RECV_INIT) {
  2788. /* RECV_INIT doesn't support registers */
  2789. if (ssa_op->result_def >= 0) {
  2790. zend_jit_close_var(stack, EX_VAR_TO_NUM(opline->result.var), start, end, flags, idx);
  2791. SET_STACK_VAR(stack, EX_VAR_TO_NUM(opline->result.var), ssa_op->result_def);
  2792. }
  2793. ssa_op++;
  2794. opline++;
  2795. idx++;
  2796. }
  2797. break;
  2798. case ZEND_BIND_GLOBAL:
  2799. ssa_op++;
  2800. opline++;
  2801. idx++;
  2802. while (opline->opcode == ZEND_BIND_GLOBAL) {
  2803. /* BIND_GLOBAL doesn't support registers */
  2804. if (ssa_op->op1_def >= 0) {
  2805. zend_jit_close_var(stack, EX_VAR_TO_NUM(opline->op1.var), start, end, flags, idx);
  2806. SET_STACK_VAR(stack, EX_VAR_TO_NUM(opline->op1.var), ssa_op->op1_def);
  2807. }
  2808. ssa_op++;
  2809. opline++;
  2810. idx++;
  2811. }
  2812. break;
  2813. default:
  2814. ssa_op += len;
  2815. idx += len;
  2816. break;
  2817. }
  2818. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  2819. /* New call frames */
  2820. zend_jit_trace_stack_frame *prev_frame = frame;
  2821. frame = zend_jit_trace_call_frame(frame, op_array);
  2822. frame->prev = prev_frame;
  2823. frame->func = (const zend_function*)p->op_array;
  2824. stack = frame->stack;
  2825. op_array = p->op_array;
  2826. jit_extension =
  2827. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  2828. op_array_ssa = &jit_extension->func_info.ssa;
  2829. j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  2830. for (i = 0; i < op_array->last_var; i++) {
  2831. SET_STACK_VAR(stack, i, j);
  2832. vars_op_array[j] = op_array;
  2833. if (ssa->vars[j].use_chain >= 0
  2834. && ssa->vars[j].alias == NO_ALIAS
  2835. && zend_jit_var_supports_reg(ssa, j)) {
  2836. start[j] = idx;
  2837. flags[j] = ZREG_LOAD;
  2838. count++;
  2839. }
  2840. j++;
  2841. }
  2842. for (i = op_array->last_var; i < op_array->last_var + op_array->T; i++) {
  2843. SET_STACK_VAR(stack, i, -1);
  2844. }
  2845. level++;
  2846. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  2847. /* Close exiting call frames */
  2848. for (i = 0; i < op_array->last_var; i++) {
  2849. zend_jit_close_var(stack, i, start, end, flags, idx-1);
  2850. }
  2851. op_array = p->op_array;
  2852. jit_extension =
  2853. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  2854. op_array_ssa = &jit_extension->func_info.ssa;
  2855. frame = zend_jit_trace_ret_frame(frame, op_array);
  2856. stack = frame->stack;
  2857. if (level == 0) {
  2858. /* New return frames */
  2859. frame->prev = NULL;
  2860. frame->func = (const zend_function*)op_array;
  2861. j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  2862. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  2863. SET_STACK_VAR(stack, i, j);
  2864. vars_op_array[j] = op_array;
  2865. if (ssa->vars[j].use_chain >= 0
  2866. && ssa->vars[j].alias == NO_ALIAS
  2867. && zend_jit_var_supports_reg(ssa, j)) {
  2868. start[j] = idx;
  2869. flags[j] = ZREG_LOAD;
  2870. count++;
  2871. }
  2872. j++;
  2873. }
  2874. } else {
  2875. level--;
  2876. }
  2877. } else if (p->op == ZEND_JIT_TRACE_END) {
  2878. break;
  2879. }
  2880. }
  2881. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  2882. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  2883. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  2884. zend_ssa_phi *phi = ssa->blocks[1].phis;
  2885. while (phi) {
  2886. i = phi->sources[1];
  2887. if (start[i] >= 0 && !ssa->vars[phi->ssa_var].no_val) {
  2888. end[i] = idx;
  2889. flags[i] &= ~ZREG_LAST_USE;
  2890. }
  2891. phi = phi->next;
  2892. }
  2893. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) {
  2894. for (i = 0; i < op_array->last_var; i++) {
  2895. if (start[i] >= 0 && !ssa->vars[i].phi_use_chain) {
  2896. end[i] = idx;
  2897. flags[i] &= ~ZREG_LAST_USE;
  2898. } else {
  2899. zend_jit_close_var(stack, i, start, end, flags, idx);
  2900. }
  2901. }
  2902. }
  2903. } else {
  2904. last_idx = idx;
  2905. for (i = 0; i < op_array->last_var; i++) {
  2906. zend_jit_close_var(stack, i, start, end, flags, idx);
  2907. }
  2908. while (frame->prev) {
  2909. frame = frame->prev;
  2910. op_array = &frame->func->op_array;
  2911. stack = frame->stack;
  2912. for (i = 0; i < op_array->last_var; i++) {
  2913. zend_jit_close_var(stack, i, start, end, flags, idx);
  2914. }
  2915. }
  2916. }
  2917. if (!count) {
  2918. free_alloca(start, use_heap);
  2919. return NULL;
  2920. }
  2921. checkpoint = zend_arena_checkpoint(CG(arena));
  2922. intervals = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_lifetime_interval));
  2923. memset(intervals, 0, sizeof(zend_lifetime_interval*) * ssa->vars_count);
  2924. list = zend_arena_alloc(&CG(arena), sizeof(zend_lifetime_interval) * count);
  2925. j = 0;
  2926. for (i = 0; i < ssa->vars_count; i++) {
  2927. if (start[i] >= 0 && end[i] >= 0) {
  2928. ZEND_ASSERT(j < count);
  2929. if ((flags[i] & ZREG_LOAD) &&
  2930. (flags[i] & ZREG_LAST_USE) &&
  2931. end[i] == ssa->vars[i].use_chain) {
  2932. /* skip life range with single use */
  2933. continue;
  2934. }
  2935. intervals[i] = &list[j];
  2936. list[j].ssa_var = i;
  2937. list[j].reg = ZREG_NONE;
  2938. list[j].flags = flags[i];
  2939. list[j].range.start = start[i];
  2940. list[j].range.end = end[i];
  2941. list[j].range.next = NULL;
  2942. list[j].hint = NULL;
  2943. list[j].used_as_hint = NULL;
  2944. list[j].list_next = NULL;
  2945. j++;
  2946. }
  2947. }
  2948. count = j;
  2949. free_alloca(start, use_heap);
  2950. start = end = NULL;
  2951. if (!count) {
  2952. zend_arena_release(&CG(arena), checkpoint);
  2953. return NULL;
  2954. }
  2955. /* Add hints */
  2956. if (parent_vars_count) {
  2957. i = trace_buffer->op_array->last_var;
  2958. if (trace_buffer->start != ZEND_JIT_TRACE_START_ENTER) {
  2959. i += trace_buffer->op_array->T;
  2960. }
  2961. if ((uint32_t)i > parent_vars_count) {
  2962. i = parent_vars_count;
  2963. }
  2964. while (i > 0) {
  2965. i--;
  2966. if (intervals[i]
  2967. && STACK_REG(parent_stack, i) != ZREG_NONE
  2968. && STACK_REG(parent_stack, i) < ZREG_NUM) {
  2969. list[j].ssa_var = - 1;
  2970. list[j].reg = STACK_REG(parent_stack, i);
  2971. list[j].flags = 0;
  2972. list[j].range.start = -1;
  2973. list[j].range.end = -1;
  2974. list[j].range.next = NULL;
  2975. list[j].hint = NULL;
  2976. list[j].used_as_hint = NULL;
  2977. list[j].list_next = NULL;
  2978. intervals[i]->hint = &list[j];
  2979. j++;
  2980. }
  2981. }
  2982. }
  2983. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  2984. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  2985. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  2986. zend_ssa_phi *phi = ssa->blocks[1].phis;
  2987. while (phi) {
  2988. if (intervals[phi->ssa_var]) {
  2989. if (intervals[phi->sources[1]]
  2990. && (ssa->var_info[phi->sources[1]].type & MAY_BE_ANY) ==
  2991. (ssa->var_info[phi->ssa_var].type & MAY_BE_ANY)) {
  2992. intervals[phi->sources[1]]->hint = intervals[phi->ssa_var];
  2993. }
  2994. }
  2995. phi = phi->next;
  2996. }
  2997. }
  2998. for (i = 0; i < ssa->vars_count; i++) {
  2999. if (intervals[i] && !intervals[i]->hint) {
  3000. if (ssa->vars[i].definition >= 0) {
  3001. uint32_t line = ssa->vars[i].definition;
  3002. const zend_op *opline = ssa_opcodes[line];
  3003. switch (opline->opcode) {
  3004. case ZEND_QM_ASSIGN:
  3005. case ZEND_POST_INC:
  3006. case ZEND_POST_DEC:
  3007. if (ssa->ops[line].op1_use >= 0 &&
  3008. intervals[ssa->ops[line].op1_use] &&
  3009. (i == ssa->ops[line].op1_def ||
  3010. (i == ssa->ops[line].result_def &&
  3011. (ssa->ops[line].op1_def < 0 ||
  3012. !intervals[ssa->ops[line].op1_def])))) {
  3013. zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use);
  3014. }
  3015. break;
  3016. case ZEND_SEND_VAR:
  3017. if (opline->op2_type == IS_CONST) {
  3018. /* Named parameters not supported in JIT */
  3019. break;
  3020. }
  3021. case ZEND_PRE_INC:
  3022. case ZEND_PRE_DEC:
  3023. if (i == ssa->ops[line].op1_def &&
  3024. ssa->ops[line].op1_use >= 0 &&
  3025. intervals[ssa->ops[line].op1_use]) {
  3026. zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use);
  3027. }
  3028. break;
  3029. case ZEND_ASSIGN:
  3030. if (ssa->ops[line].op2_use >= 0 &&
  3031. intervals[ssa->ops[line].op2_use] &&
  3032. (i == ssa->ops[line].op2_def ||
  3033. (i == ssa->ops[line].op1_def &&
  3034. (ssa->ops[line].op2_def < 0 ||
  3035. !intervals[ssa->ops[line].op2_def])) ||
  3036. (i == ssa->ops[line].result_def &&
  3037. (ssa->ops[line].op2_def < 0 ||
  3038. !intervals[ssa->ops[line].op2_def]) &&
  3039. (ssa->ops[line].op1_def < 0 ||
  3040. !intervals[ssa->ops[line].op1_def])))) {
  3041. zend_jit_add_hint(intervals, i, ssa->ops[line].op2_use);
  3042. }
  3043. break;
  3044. case ZEND_SUB:
  3045. case ZEND_ADD:
  3046. case ZEND_MUL:
  3047. case ZEND_BW_OR:
  3048. case ZEND_BW_AND:
  3049. case ZEND_BW_XOR:
  3050. if (i == ssa->ops[line].result_def) {
  3051. if (ssa->ops[line].op1_use >= 0 &&
  3052. intervals[ssa->ops[line].op1_use] &&
  3053. ssa->ops[line].op1_use_chain < 0 &&
  3054. !ssa->vars[ssa->ops[line].op1_use].phi_use_chain &&
  3055. (ssa->var_info[i].type & MAY_BE_ANY) ==
  3056. (ssa->var_info[ssa->ops[line].op1_use].type & MAY_BE_ANY)) {
  3057. zend_ssa_phi *phi = ssa->vars[ssa->ops[line].op1_use].definition_phi;
  3058. if (phi &&
  3059. intervals[phi->sources[1]] &&
  3060. intervals[phi->sources[1]]->hint == intervals[ssa->ops[line].op1_use]) {
  3061. break;
  3062. }
  3063. zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use);
  3064. } else if (opline->opcode != ZEND_SUB &&
  3065. ssa->ops[line].op2_use >= 0 &&
  3066. intervals[ssa->ops[line].op2_use] &&
  3067. ssa->ops[line].op2_use_chain < 0 &&
  3068. !ssa->vars[ssa->ops[line].op2_use].phi_use_chain &&
  3069. (ssa->var_info[i].type & MAY_BE_ANY) ==
  3070. (ssa->var_info[ssa->ops[line].op2_use].type & MAY_BE_ANY)) {
  3071. zend_ssa_phi *phi = ssa->vars[ssa->ops[line].op2_use].definition_phi;
  3072. if (phi &&
  3073. intervals[phi->sources[1]] &&
  3074. intervals[phi->sources[1]]->hint == intervals[ssa->ops[line].op2_use]) {
  3075. break;
  3076. }
  3077. zend_jit_add_hint(intervals, i, ssa->ops[line].op2_use);
  3078. }
  3079. }
  3080. break;
  3081. }
  3082. }
  3083. }
  3084. }
  3085. list = zend_jit_sort_intervals(intervals, ssa->vars_count);
  3086. if (list) {
  3087. ival = list;
  3088. while (ival) {
  3089. if (ival->hint) {
  3090. ival->hint->used_as_hint = ival;
  3091. }
  3092. ival = ival->list_next;
  3093. }
  3094. }
  3095. if (list) {
  3096. if (JIT_G(debug) & ZEND_JIT_DEBUG_REG_ALLOC) {
  3097. fprintf(stderr, "---- TRACE %d Live Ranges\n", ZEND_JIT_TRACE_NUM);
  3098. ival = list;
  3099. while (ival) {
  3100. zend_jit_dump_lifetime_interval(vars_op_array[ival->ssa_var], ssa, ival);
  3101. ival = ival->list_next;
  3102. }
  3103. }
  3104. }
  3105. /* Linear Scan Register Allocation (op_array is not actually used, only fn_flags matters) */
  3106. list = zend_jit_linear_scan(&dummy_op_array, ssa_opcodes, ssa, list);
  3107. if (list) {
  3108. zend_lifetime_interval *ival, *next;
  3109. memset(intervals, 0, ssa->vars_count * sizeof(zend_lifetime_interval*));
  3110. ival = list;
  3111. count = 0;
  3112. while (ival != NULL) {
  3113. ZEND_ASSERT(ival->reg != ZREG_NONE);
  3114. count++;
  3115. next = ival->list_next;
  3116. ival->list_next = intervals[ival->ssa_var];
  3117. intervals[ival->ssa_var] = ival;
  3118. ival = next;
  3119. }
  3120. if (!count) {
  3121. zend_arena_release(&CG(arena), checkpoint);
  3122. return NULL;
  3123. }
  3124. /* Add LOAD flag to registers that can't reuse register from parent trace */
  3125. if (parent_vars_count) {
  3126. i = trace_buffer->op_array->last_var;
  3127. if (trace_buffer->start != ZEND_JIT_TRACE_START_ENTER) {
  3128. i += trace_buffer->op_array->T;
  3129. }
  3130. if ((uint32_t)i > parent_vars_count) {
  3131. i = parent_vars_count;
  3132. }
  3133. while (i > 0) {
  3134. i--;
  3135. if (intervals[i] && intervals[i]->reg != STACK_REG(parent_stack, i)) {
  3136. intervals[i]->flags |= ZREG_LOAD;
  3137. }
  3138. }
  3139. }
  3140. /* SSA resolution */
  3141. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  3142. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  3143. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  3144. zend_ssa_phi *phi = ssa->blocks[1].phis;
  3145. while (phi) {
  3146. int def = phi->ssa_var;
  3147. int use = phi->sources[1];
  3148. if (intervals[def]) {
  3149. if (!intervals[use]) {
  3150. intervals[def]->flags |= ZREG_LOAD;
  3151. if ((intervals[def]->flags & ZREG_LAST_USE)
  3152. && ssa->vars[def].use_chain >= 0
  3153. && ssa->vars[def].use_chain == intervals[def]->range.end) {
  3154. /* remove interval used once */
  3155. intervals[def] = NULL;
  3156. count--;
  3157. }
  3158. } else if (intervals[def]->reg != intervals[use]->reg) {
  3159. intervals[def]->flags |= ZREG_LOAD;
  3160. if (ssa->vars[use].use_chain >= 0) {
  3161. intervals[use]->flags |= ZREG_STORE;
  3162. } else {
  3163. intervals[use] = NULL;
  3164. count--;
  3165. }
  3166. } else {
  3167. use = phi->sources[0];
  3168. ZEND_ASSERT(!intervals[use]);
  3169. intervals[use] = zend_arena_alloc(&CG(arena), sizeof(zend_lifetime_interval));
  3170. intervals[use]->ssa_var = phi->sources[0];
  3171. intervals[use]->reg = intervals[def]->reg;
  3172. intervals[use]->flags = ZREG_LOAD;
  3173. intervals[use]->range.start = 0;
  3174. intervals[use]->range.end = 0;
  3175. intervals[use]->range.next = NULL;
  3176. intervals[use]->hint = NULL;
  3177. intervals[use]->used_as_hint = NULL;
  3178. intervals[use]->list_next = NULL;
  3179. }
  3180. } else if (intervals[use]
  3181. && (!ssa->vars[def].no_val
  3182. || ssa->var_info[def].type != ssa->var_info[use].type)) {
  3183. if (ssa->vars[use].use_chain >= 0) {
  3184. intervals[use]->flags |= ZREG_STORE;
  3185. } else {
  3186. intervals[use] = NULL;
  3187. count--;
  3188. }
  3189. }
  3190. phi = phi->next;
  3191. }
  3192. } else {
  3193. for (i = 0; i < ssa->vars_count; i++) {
  3194. if (intervals[i]
  3195. && intervals[i]->range.end == last_idx
  3196. && !(intervals[i]->flags & (ZREG_LOAD|ZREG_STORE))) {
  3197. intervals[i]->flags |= ZREG_STORE;
  3198. }
  3199. }
  3200. }
  3201. if (!count) {
  3202. zend_arena_release(&CG(arena), checkpoint);
  3203. return NULL;
  3204. }
  3205. if (JIT_G(debug) & ZEND_JIT_DEBUG_REG_ALLOC) {
  3206. fprintf(stderr, "---- TRACE %d Allocated Live Ranges\n", ZEND_JIT_TRACE_NUM);
  3207. for (i = 0; i < ssa->vars_count; i++) {
  3208. ival = intervals[i];
  3209. while (ival) {
  3210. zend_jit_dump_lifetime_interval(vars_op_array[ival->ssa_var], ssa, ival);
  3211. ival = ival->list_next;
  3212. }
  3213. }
  3214. }
  3215. return intervals;
  3216. }
  3217. zend_arena_release(&CG(arena), checkpoint); //???
  3218. return NULL;
  3219. }
  3220. static void zend_jit_trace_clenup_stack(zend_jit_trace_stack *stack, const zend_op *opline, const zend_ssa_op *ssa_op, const zend_ssa *ssa, zend_lifetime_interval **ra)
  3221. {
  3222. uint32_t line = ssa_op - ssa->ops;
  3223. if (ssa_op->op1_use >= 0
  3224. && ra[ssa_op->op1_use]
  3225. && ra[ssa_op->op1_use]->range.end == line) {
  3226. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE);
  3227. }
  3228. if (ssa_op->op2_use >= 0
  3229. && ra[ssa_op->op2_use]
  3230. && ra[ssa_op->op2_use]->range.end == line) {
  3231. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->op2.var), ZREG_NONE);
  3232. }
  3233. if (ssa_op->result_use >= 0
  3234. && ra[ssa_op->result_use]
  3235. && ra[ssa_op->result_use]->range.end == line) {
  3236. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_NONE);
  3237. }
  3238. }
  3239. static void zend_jit_trace_setup_ret_counter(const zend_op *opline, size_t offset)
  3240. {
  3241. zend_op *next_opline = (zend_op*)(opline + 1);
  3242. if (JIT_G(hot_return) && !ZEND_OP_TRACE_INFO(next_opline, offset)->trace_flags) {
  3243. ZEND_ASSERT(zend_jit_ret_trace_counter_handler != NULL);
  3244. if (!ZEND_OP_TRACE_INFO(next_opline, offset)->counter) {
  3245. ZEND_OP_TRACE_INFO(next_opline, offset)->counter =
  3246. &zend_jit_hot_counters[ZEND_JIT_COUNTER_NUM];
  3247. ZEND_JIT_COUNTER_NUM = (ZEND_JIT_COUNTER_NUM + 1) % ZEND_HOT_COUNTERS_COUNT;
  3248. }
  3249. ZEND_OP_TRACE_INFO(next_opline, offset)->trace_flags = ZEND_JIT_TRACE_START_RETURN;
  3250. next_opline->handler = (const void*)zend_jit_ret_trace_counter_handler;
  3251. }
  3252. }
  3253. static bool zend_jit_may_delay_fetch_this(const zend_op_array *op_array, zend_ssa *ssa, const zend_op **ssa_opcodes, const zend_ssa_op *ssa_op)
  3254. {
  3255. int var = ssa_op->result_def;
  3256. int i;
  3257. int use = ssa->vars[var].use_chain;
  3258. const zend_op *opline;
  3259. if (use < 0
  3260. || ssa->vars[var].phi_use_chain
  3261. || ssa->ops[use].op1_use != var
  3262. || ssa->ops[use].op1_use_chain != -1) {
  3263. return 0;
  3264. }
  3265. opline = ssa_opcodes[use];
  3266. if (opline->opcode == ZEND_INIT_METHOD_CALL) {
  3267. return (opline->op2_type == IS_CONST &&
  3268. Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_STRING);
  3269. } else if (opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
  3270. if (!JIT_G(current_frame)
  3271. || !JIT_G(current_frame)->call
  3272. || !JIT_G(current_frame)->call->func
  3273. || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
  3274. return 0;
  3275. }
  3276. } else if (opline->opcode != ZEND_FETCH_OBJ_R
  3277. && opline->opcode != ZEND_FETCH_OBJ_IS
  3278. && opline->opcode != ZEND_FETCH_OBJ_W
  3279. && opline->opcode != ZEND_ASSIGN_OBJ
  3280. && opline->opcode != ZEND_ASSIGN_OBJ_OP
  3281. && opline->opcode != ZEND_PRE_INC_OBJ
  3282. && opline->opcode != ZEND_PRE_DEC_OBJ
  3283. && opline->opcode != ZEND_POST_INC_OBJ
  3284. && opline->opcode != ZEND_POST_DEC_OBJ) {
  3285. return 0;
  3286. }
  3287. if (opline->op2_type != IS_CONST
  3288. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  3289. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  3290. return 0;
  3291. }
  3292. if (opline->opcode == ZEND_ASSIGN_OBJ_OP) {
  3293. if (opline->op1_type == IS_CV
  3294. && (opline+1)->op1_type == IS_CV
  3295. && (opline+1)->op1.var == opline->op1.var) {
  3296. /* skip $a->prop += $a; */
  3297. return 0;
  3298. }
  3299. if (!zend_jit_supported_binary_op(
  3300. opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
  3301. return 0;
  3302. }
  3303. }
  3304. for (i = ssa->vars[var].definition; i < use; i++) {
  3305. if (ssa_opcodes[i]->opcode == ZEND_DO_UCALL
  3306. || ssa_opcodes[i]->opcode == ZEND_DO_FCALL_BY_NAME
  3307. || ssa_opcodes[i]->opcode == ZEND_DO_FCALL
  3308. || ssa_opcodes[i]->opcode == ZEND_INCLUDE_OR_EVAL) {
  3309. return 0;
  3310. }
  3311. }
  3312. return 1;
  3313. }
  3314. static int zend_jit_trace_stack_needs_deoptimization(zend_jit_trace_stack *stack, uint32_t stack_size)
  3315. {
  3316. uint32_t i;
  3317. for (i = 0; i < stack_size; i++) {
  3318. if (STACK_REG(stack, i) != ZREG_NONE
  3319. && !(STACK_FLAGS(stack, i) & (ZREG_LOAD|ZREG_STORE))) {
  3320. return 1;
  3321. }
  3322. }
  3323. return 0;
  3324. }
  3325. static int zend_jit_trace_exit_needs_deoptimization(uint32_t trace_num, uint32_t exit_num)
  3326. {
  3327. const zend_op *opline = zend_jit_traces[trace_num].exit_info[exit_num].opline;
  3328. uint32_t flags = zend_jit_traces[trace_num].exit_info[exit_num].flags;
  3329. uint32_t stack_size;
  3330. zend_jit_trace_stack *stack;
  3331. if (opline || (flags & (ZEND_JIT_EXIT_RESTORE_CALL|ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2))) {
  3332. return 1;
  3333. }
  3334. stack_size = zend_jit_traces[trace_num].exit_info[exit_num].stack_size;
  3335. stack = zend_jit_traces[trace_num].stack_map + zend_jit_traces[trace_num].exit_info[exit_num].stack_offset;
  3336. return zend_jit_trace_stack_needs_deoptimization(stack, stack_size);
  3337. }
  3338. static int zend_jit_trace_deoptimization(dasm_State **Dst,
  3339. uint32_t flags,
  3340. const zend_op *opline,
  3341. zend_jit_trace_stack *parent_stack,
  3342. int parent_vars_count,
  3343. zend_ssa *ssa,
  3344. zend_jit_trace_stack *stack,
  3345. zend_lifetime_interval **ra,
  3346. bool polymorphic_side_trace)
  3347. {
  3348. int i;
  3349. bool has_constants = 0;
  3350. bool has_unsaved_vars = 0;
  3351. // TODO: Merge this loop with the following register LOAD loop to implement parallel move ???
  3352. for (i = 0; i < parent_vars_count; i++) {
  3353. int8_t reg = STACK_REG(parent_stack, i);
  3354. if (reg != ZREG_NONE) {
  3355. if (reg < ZREG_NUM) {
  3356. if (ssa && ssa->vars[i].no_val) {
  3357. /* pass */
  3358. } else if (ra && ra[i] && ra[i]->reg == reg) {
  3359. /* register already loaded by parent trace */
  3360. if (stack) {
  3361. SET_STACK_REG_EX(stack, i, reg, STACK_FLAGS(parent_stack, i));
  3362. }
  3363. has_unsaved_vars = 1;
  3364. } else {
  3365. uint8_t type = STACK_TYPE(parent_stack, i);
  3366. if (!(STACK_FLAGS(parent_stack, i) & (ZREG_LOAD|ZREG_STORE))
  3367. && !zend_jit_store_var(Dst, 1 << type, i, reg,
  3368. STACK_MEM_TYPE(parent_stack, i) != type)) {
  3369. return 0;
  3370. }
  3371. if (stack) {
  3372. SET_STACK_TYPE(stack, i, type, 1);
  3373. }
  3374. }
  3375. } else {
  3376. /* delay custom deoptimization instructions to prevent register clobbering */
  3377. has_constants = 1;
  3378. }
  3379. }
  3380. }
  3381. if (has_unsaved_vars
  3382. && (has_constants
  3383. || (flags & (ZEND_JIT_EXIT_RESTORE_CALL|ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)))) {
  3384. for (i = 0; i < parent_vars_count; i++) {
  3385. int8_t reg = STACK_REG(parent_stack, i);
  3386. if (reg != ZREG_NONE) {
  3387. if (reg < ZREG_NUM) {
  3388. if (ssa && ssa->vars[i].no_val) {
  3389. /* pass */
  3390. } else if (ra && ra[i] && ra[i]->reg == reg) {
  3391. uint8_t type = STACK_TYPE(parent_stack, i);
  3392. if (stack) {
  3393. SET_STACK_TYPE(stack, i, type, 1);
  3394. }
  3395. if (!(STACK_FLAGS(parent_stack, i) & (ZREG_LOAD|ZREG_STORE))
  3396. && !zend_jit_store_var(Dst, 1 << type, i, reg,
  3397. STACK_MEM_TYPE(parent_stack, i) != type)) {
  3398. return 0;
  3399. }
  3400. }
  3401. }
  3402. }
  3403. }
  3404. }
  3405. if (has_constants) {
  3406. for (i = 0; i < parent_vars_count; i++) {
  3407. int8_t reg = STACK_REG(parent_stack, i);
  3408. if (reg != ZREG_NONE) {
  3409. if (reg < ZREG_NUM) {
  3410. /* pass */
  3411. } else if (reg == ZREG_THIS) {
  3412. if (polymorphic_side_trace) {
  3413. ssa->var_info[i].delayed_fetch_this = 1;
  3414. if (stack) {
  3415. SET_STACK_REG(stack, i, ZREG_THIS);
  3416. }
  3417. } else if (!zend_jit_load_this(Dst, EX_NUM_TO_VAR(i))) {
  3418. return 0;
  3419. }
  3420. } else {
  3421. if (reg == ZREG_ZVAL_COPY_GPR0
  3422. &&!zend_jit_escape_if_undef_r0(Dst, i, flags, opline)) {
  3423. return 0;
  3424. }
  3425. if (!zend_jit_store_const(Dst, i, reg)) {
  3426. return 0;
  3427. }
  3428. }
  3429. }
  3430. }
  3431. }
  3432. if (flags & ZEND_JIT_EXIT_RESTORE_CALL) {
  3433. if (!zend_jit_save_call_chain(Dst, -1)) {
  3434. return 0;
  3435. }
  3436. }
  3437. if (flags & ZEND_JIT_EXIT_FREE_OP2) {
  3438. const zend_op *op = opline - 1;
  3439. if (!zend_jit_free_op(Dst, op, -1, op->op2.var)) {
  3440. return 0;
  3441. }
  3442. }
  3443. if (flags & ZEND_JIT_EXIT_FREE_OP1) {
  3444. const zend_op *op = opline - 1;
  3445. if (!zend_jit_free_op(Dst, op, -1, op->op1.var)) {
  3446. return 0;
  3447. }
  3448. }
  3449. if (flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) {
  3450. if (!zend_jit_check_exception(Dst)) {
  3451. return 0;
  3452. }
  3453. }
  3454. if ((flags & ZEND_JIT_EXIT_METHOD_CALL) && !polymorphic_side_trace) {
  3455. if (!zend_jit_free_trampoline(Dst)) {
  3456. return 0;
  3457. }
  3458. }
  3459. return 1;
  3460. }
  3461. static void zend_jit_trace_set_var_range(zend_ssa_var_info *info, zend_long min, zend_long max)
  3462. {
  3463. info->has_range = 1;
  3464. info->range.min = min;
  3465. info->range.max = max;
  3466. info->range.underflow = 0;
  3467. info->range.overflow = 0;
  3468. }
  3469. static void zend_jit_trace_update_condition_ranges(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, zend_ssa *ssa, bool exit_if_true)
  3470. {
  3471. zend_long op1_min, op1_max, op2_min, op2_max;
  3472. if ((OP1_INFO() & MAY_BE_ANY) != MAY_BE_LONG
  3473. || (OP1_INFO() & MAY_BE_ANY) != MAY_BE_LONG) {
  3474. return;
  3475. }
  3476. op1_min = OP1_MIN_RANGE();
  3477. op1_max = OP1_MAX_RANGE();
  3478. op2_min = OP2_MIN_RANGE();
  3479. op2_max = OP2_MAX_RANGE();
  3480. switch (opline->opcode) {
  3481. case ZEND_IS_EQUAL:
  3482. case ZEND_CASE:
  3483. case ZEND_IS_IDENTICAL:
  3484. case ZEND_CASE_STRICT:
  3485. case ZEND_IS_NOT_IDENTICAL:
  3486. if (!exit_if_true) {
  3487. /* op1 == op2 */
  3488. if (ssa_op->op1_use >= 0) {
  3489. zend_jit_trace_set_var_range(
  3490. &ssa->var_info[ssa_op->op1_use],
  3491. MAX(op1_min, op2_min),
  3492. MIN(op1_max, op2_max));
  3493. }
  3494. if (ssa_op->op2_use >= 0) {
  3495. zend_jit_trace_set_var_range(
  3496. &ssa->var_info[ssa_op->op2_use],
  3497. MAX(op2_min, op1_min),
  3498. MIN(op2_max, op1_max));
  3499. }
  3500. }
  3501. break;
  3502. case ZEND_IS_NOT_EQUAL:
  3503. if (exit_if_true) {
  3504. /* op1 == op2 */
  3505. if (ssa_op->op1_use >= 0) {
  3506. zend_jit_trace_set_var_range(
  3507. &ssa->var_info[ssa_op->op1_use],
  3508. MAX(op1_min, op2_min),
  3509. MIN(op1_max, op2_max));
  3510. }
  3511. if (ssa_op->op2_use >= 0) {
  3512. zend_jit_trace_set_var_range(
  3513. &ssa->var_info[ssa_op->op2_use],
  3514. MAX(op2_min, op1_min),
  3515. MIN(op2_max, op1_max));
  3516. }
  3517. }
  3518. break;
  3519. case ZEND_IS_SMALLER_OR_EQUAL:
  3520. if (!exit_if_true) {
  3521. /* op1 <= op2 */
  3522. if (ssa_op->op1_use >= 0) {
  3523. zend_jit_trace_set_var_range(
  3524. &ssa->var_info[ssa_op->op1_use],
  3525. op1_min,
  3526. MIN(op1_max, op2_max));
  3527. }
  3528. if (ssa_op->op2_use >= 0) {
  3529. zend_jit_trace_set_var_range(
  3530. &ssa->var_info[ssa_op->op2_use],
  3531. MAX(op2_min, op1_min),
  3532. op2_max);
  3533. }
  3534. } else {
  3535. /* op1 > op2 */
  3536. if (ssa_op->op1_use >= 0) {
  3537. zend_jit_trace_set_var_range(
  3538. &ssa->var_info[ssa_op->op1_use],
  3539. op2_min != ZEND_LONG_MAX ? MAX(op1_min, op2_min + 1) : op1_min,
  3540. op1_max);
  3541. }
  3542. if (ssa_op->op2_use >= 0) {
  3543. zend_jit_trace_set_var_range(
  3544. &ssa->var_info[ssa_op->op2_use],
  3545. op2_min,
  3546. op2_max != ZEND_LONG_MIN ?MIN(op2_max, op1_max - 1) : op1_max);
  3547. }
  3548. }
  3549. break;
  3550. case ZEND_IS_SMALLER:
  3551. if (!exit_if_true) {
  3552. /* op1 < op2 */
  3553. if (ssa_op->op1_use >= 0) {
  3554. zend_jit_trace_set_var_range(
  3555. &ssa->var_info[ssa_op->op1_use],
  3556. op1_min,
  3557. op2_max != ZEND_LONG_MIN ? MIN(op1_max, op2_max - 1) : op1_max);
  3558. }
  3559. if (ssa_op->op2_use >= 0) {
  3560. zend_jit_trace_set_var_range(
  3561. &ssa->var_info[ssa_op->op2_use],
  3562. op1_min != ZEND_LONG_MAX ? MAX(op2_min, op1_min + 1) : op2_min,
  3563. op2_max);
  3564. }
  3565. } else {
  3566. /* op1 >= op2 */
  3567. if (ssa_op->op1_use >= 0) {
  3568. zend_jit_trace_set_var_range(
  3569. &ssa->var_info[ssa_op->op1_use],
  3570. MAX(op1_min, op2_min),
  3571. op1_max);
  3572. }
  3573. if (ssa_op->op2_use >= 0) {
  3574. zend_jit_trace_set_var_range(
  3575. &ssa->var_info[ssa_op->op2_use],
  3576. op2_min,
  3577. MIN(op2_max, op1_max));
  3578. }
  3579. }
  3580. break;
  3581. }
  3582. }
  3583. static bool zend_jit_may_skip_comparison(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_ssa *ssa, const zend_op **ssa_opcodes, const zend_op_array *op_array)
  3584. {
  3585. zend_uchar prev_opcode;
  3586. if (opline->op1_type == IS_CONST
  3587. && Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_LONG
  3588. && Z_LVAL_P(RT_CONSTANT(opline, opline->op1)) == 0) {
  3589. if (ssa_op->op2_use >= 0) {
  3590. if ((ssa_op-1)->op1_def == ssa_op->op2_use) {
  3591. ssa_op--;
  3592. opline = ssa_opcodes[ssa_op - ssa->ops];
  3593. prev_opcode = opline->opcode;
  3594. if (prev_opcode == ZEND_PRE_INC
  3595. || prev_opcode == ZEND_PRE_DEC
  3596. || prev_opcode == ZEND_POST_INC
  3597. || prev_opcode == ZEND_POST_DEC) {
  3598. return (OP1_INFO() & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)-MAY_BE_LONG)) == 0;
  3599. }
  3600. } else if ((ssa_op-1)->result_def == ssa_op->op2_use) {
  3601. ssa_op--;
  3602. opline = ssa_opcodes[ssa_op - ssa->ops];
  3603. prev_opcode = opline->opcode;
  3604. if (prev_opcode == ZEND_ADD
  3605. || prev_opcode == ZEND_SUB) {
  3606. return (OP1_INFO() & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)-MAY_BE_LONG)) == 0 &&
  3607. (OP2_INFO() & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)-MAY_BE_LONG)) == 0;
  3608. }
  3609. }
  3610. }
  3611. } else if (opline->op2_type == IS_CONST
  3612. && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG
  3613. && Z_LVAL_P(RT_CONSTANT(opline, opline->op2)) == 0) {
  3614. if (ssa_op->op1_use >= 0) {
  3615. if ((ssa_op-1)->op1_def == ssa_op->op1_use) {
  3616. ssa_op--;
  3617. opline = ssa_opcodes[ssa_op - ssa->ops];
  3618. prev_opcode = opline->opcode;
  3619. if (prev_opcode == ZEND_PRE_INC
  3620. || prev_opcode == ZEND_PRE_DEC
  3621. || prev_opcode == ZEND_POST_INC
  3622. || prev_opcode == ZEND_POST_DEC) {
  3623. return (OP1_INFO() & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)-MAY_BE_LONG)) == 0;
  3624. }
  3625. } else if ((ssa_op-1)->result_def == ssa_op->op1_use) {
  3626. ssa_op--;
  3627. opline = ssa_opcodes[ssa_op - ssa->ops];
  3628. prev_opcode = opline->opcode;
  3629. if (prev_opcode == ZEND_ADD
  3630. || prev_opcode == ZEND_SUB) {
  3631. return (OP1_INFO() & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)-MAY_BE_LONG)) == 0 &&
  3632. (OP2_INFO() & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)-MAY_BE_LONG)) == 0;
  3633. }
  3634. }
  3635. }
  3636. } else {
  3637. const zend_ssa_op *prev_ssa_op = ssa_op - 1;
  3638. prev_opcode = ssa_opcodes[prev_ssa_op - ssa->ops]->opcode;
  3639. if ((prev_opcode == ZEND_JMPZ || prev_opcode == ZEND_JMPNZ)
  3640. && prev_ssa_op != ssa->ops
  3641. && prev_ssa_op->op1_use >= 0
  3642. && prev_ssa_op->op1_use == (prev_ssa_op-1)->result_def) {
  3643. prev_ssa_op--;
  3644. prev_opcode = ssa_opcodes[prev_ssa_op - ssa->ops]->opcode;
  3645. }
  3646. if (ssa_op->op1_use == prev_ssa_op->op1_use
  3647. && ssa_op->op2_use == prev_ssa_op->op2_use) {
  3648. if (prev_opcode == ZEND_IS_EQUAL
  3649. || prev_opcode == ZEND_IS_NOT_EQUAL
  3650. || prev_opcode == ZEND_IS_SMALLER
  3651. || prev_opcode == ZEND_IS_SMALLER_OR_EQUAL
  3652. || prev_opcode == ZEND_CASE
  3653. || prev_opcode == ZEND_IS_IDENTICAL
  3654. || prev_opcode == ZEND_IS_NOT_IDENTICAL
  3655. || prev_opcode == ZEND_CASE_STRICT) {
  3656. if (ssa_op->op1_use < 0) {
  3657. if (RT_CONSTANT(opline, opline->op1) != RT_CONSTANT(&ssa_opcodes[prev_ssa_op - ssa->ops], ssa_opcodes[prev_ssa_op - ssa->ops]->op1)) {
  3658. return 0;
  3659. }
  3660. }
  3661. if (ssa_op->op2_use < 0) {
  3662. if (RT_CONSTANT(opline, opline->op2) != RT_CONSTANT(&ssa_opcodes[prev_ssa_op - ssa->ops], ssa_opcodes[prev_ssa_op - ssa->ops]->op2)) {
  3663. return 0;
  3664. }
  3665. }
  3666. return 1;
  3667. }
  3668. }
  3669. }
  3670. return 0;
  3671. }
  3672. static bool zend_jit_trace_next_is_send_result(const zend_op *opline,
  3673. zend_jit_trace_rec *p,
  3674. zend_jit_trace_stack_frame *frame)
  3675. {
  3676. if (opline->result_type == IS_TMP_VAR
  3677. && (p+1)->op == ZEND_JIT_TRACE_VM
  3678. && (p+1)->opline == opline + 1
  3679. && ((opline+1)->opcode == ZEND_SEND_VAL
  3680. || ((opline+1)->opcode == ZEND_SEND_VAL_EX
  3681. && frame
  3682. && frame->call
  3683. && frame->call->func
  3684. && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
  3685. && (opline+1)->op1_type == IS_TMP_VAR
  3686. && (opline+1)->op2_type != IS_CONST /* Named parameters not supported in JIT */
  3687. && (opline+1)->op1.var == opline->result.var) {
  3688. if (frame->call && frame->call->func) {
  3689. uint8_t res_type = (p+1)->op1_type;
  3690. if (res_type != IS_UNKNOWN && !(res_type & IS_TRACE_REFERENCE) ) {
  3691. zend_jit_trace_send_type(opline+1, frame->call, res_type);
  3692. }
  3693. }
  3694. return 1;
  3695. }
  3696. return 0;
  3697. }
  3698. static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t parent_trace, uint32_t exit_num)
  3699. {
  3700. const void *handler = NULL;
  3701. dasm_State* dasm_state = NULL;
  3702. zend_script *script = NULL;
  3703. zend_lifetime_interval **ra = NULL;
  3704. zend_string *name = NULL;
  3705. void *checkpoint;
  3706. const zend_op_array *op_array;
  3707. zend_ssa *ssa, *op_array_ssa;
  3708. const zend_op **ssa_opcodes;
  3709. zend_jit_trace_rec *p;
  3710. zend_jit_op_array_trace_extension *jit_extension;
  3711. int num_op_arrays = 0;
  3712. zend_jit_trace_info *t;
  3713. const zend_op_array *op_arrays[ZEND_JIT_TRACE_MAX_FUNCS];
  3714. zend_uchar smart_branch_opcode;
  3715. const void *exit_addr;
  3716. uint32_t op1_info, op1_def_info, op2_info, res_info, res_use_info, op1_data_info;
  3717. bool send_result = 0;
  3718. bool skip_comparison;
  3719. zend_jit_addr op1_addr, op1_def_addr, op2_addr, op2_def_addr, res_addr;
  3720. zend_class_entry *ce;
  3721. bool ce_is_instanceof;
  3722. bool on_this = 0;
  3723. bool delayed_fetch_this = 0;
  3724. bool avoid_refcounting = 0;
  3725. bool polymorphic_side_trace =
  3726. parent_trace &&
  3727. (zend_jit_traces[parent_trace].exit_info[exit_num].flags & ZEND_JIT_EXIT_METHOD_CALL);
  3728. uint32_t i;
  3729. zend_jit_trace_stack_frame *frame, *top, *call;
  3730. zend_jit_trace_stack *stack;
  3731. zend_uchar res_type = IS_UNKNOWN;
  3732. const zend_op *opline, *orig_opline;
  3733. const zend_ssa_op *ssa_op, *orig_ssa_op;
  3734. int checked_stack;
  3735. int peek_checked_stack;
  3736. uint32_t frame_flags = 0;
  3737. JIT_G(current_trace) = trace_buffer;
  3738. checkpoint = zend_arena_checkpoint(CG(arena));
  3739. ssa = zend_jit_trace_build_tssa(trace_buffer, parent_trace, exit_num, script, op_arrays, &num_op_arrays);
  3740. if (!ssa) {
  3741. goto jit_cleanup;
  3742. }
  3743. ssa_opcodes = ((zend_tssa*)ssa)->tssa_opcodes;
  3744. /* Register allocation */
  3745. if ((JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL))
  3746. && JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
  3747. ra = zend_jit_trace_allocate_registers(trace_buffer, ssa, parent_trace, exit_num);
  3748. }
  3749. p = trace_buffer;
  3750. ZEND_ASSERT(p->op == ZEND_JIT_TRACE_START);
  3751. op_array = p->op_array;
  3752. frame = JIT_G(current_frame);
  3753. top = zend_jit_trace_call_frame(frame, op_array);
  3754. TRACE_FRAME_INIT(frame, op_array, TRACE_FRAME_MASK_UNKNOWN_RETURN, -1);
  3755. frame->used_stack = checked_stack = peek_checked_stack = 0;
  3756. stack = frame->stack;
  3757. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  3758. SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
  3759. }
  3760. opline = p[1].opline;
  3761. name = zend_jit_trace_name(op_array, opline->lineno);
  3762. p += ZEND_JIT_TRACE_START_REC_SIZE;
  3763. dasm_init(&dasm_state, DASM_MAXSECTION);
  3764. dasm_setupglobal(&dasm_state, dasm_labels, zend_lb_MAX);
  3765. dasm_setup(&dasm_state, dasm_actions);
  3766. jit_extension =
  3767. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  3768. op_array_ssa = &jit_extension->func_info.ssa;
  3769. dasm_growpc(&dasm_state, 2); /* =>0: loop header */
  3770. /* =>1: end of code */
  3771. zend_jit_align_func(&dasm_state);
  3772. if (!parent_trace) {
  3773. zend_jit_prologue(&dasm_state);
  3774. }
  3775. zend_jit_trace_begin(&dasm_state, ZEND_JIT_TRACE_NUM,
  3776. parent_trace ? &zend_jit_traces[parent_trace] : NULL, exit_num);
  3777. if (!parent_trace) {
  3778. zend_jit_set_last_valid_opline(opline);
  3779. zend_jit_track_last_valid_opline();
  3780. } else {
  3781. if (zend_jit_traces[parent_trace].exit_info[exit_num].opline == NULL) {
  3782. zend_jit_trace_opline_guard(&dasm_state, opline);
  3783. } else {
  3784. zend_jit_reset_last_valid_opline();
  3785. }
  3786. }
  3787. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
  3788. int last_var;
  3789. int parent_vars_count = 0;
  3790. zend_jit_trace_stack *parent_stack = NULL;
  3791. int used_stack = ((zend_tssa*)ssa)->used_stack;
  3792. if (used_stack > 0) {
  3793. peek_checked_stack = used_stack;
  3794. if (!zend_jit_stack_check(&dasm_state, opline, used_stack)) {
  3795. goto jit_failure;
  3796. }
  3797. }
  3798. if (parent_trace) {
  3799. parent_vars_count = MIN(zend_jit_traces[parent_trace].exit_info[exit_num].stack_size,
  3800. op_array->last_var + op_array->T);
  3801. if (parent_vars_count) {
  3802. parent_stack =
  3803. zend_jit_traces[parent_trace].stack_map +
  3804. zend_jit_traces[parent_trace].exit_info[exit_num].stack_offset;
  3805. }
  3806. }
  3807. last_var = op_array->last_var;
  3808. if (trace_buffer->start != ZEND_JIT_TRACE_START_ENTER) {
  3809. last_var += op_array->T;
  3810. }
  3811. for (i = 0; i < last_var; i++) {
  3812. uint32_t info = ssa->var_info[i].type;
  3813. if (!(info & MAY_BE_GUARD) && has_concrete_type(info)) {
  3814. uint8_t type, mem_type;
  3815. type = concrete_type(info);
  3816. if (i < parent_vars_count
  3817. && STACK_TYPE(parent_stack, i) == type) {
  3818. mem_type = STACK_MEM_TYPE(parent_stack, i);
  3819. if (mem_type != IS_UNKNOWN) {
  3820. SET_STACK_TYPE(stack, i, mem_type, 1);
  3821. }
  3822. SET_STACK_TYPE(stack, i, type, 0);
  3823. } else {
  3824. SET_STACK_TYPE(stack, i, type, 1);
  3825. }
  3826. } else if (ssa->vars[i].alias != NO_ALIAS) {
  3827. SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
  3828. } else if (i < parent_vars_count
  3829. && STACK_TYPE(parent_stack, i) != IS_UNKNOWN) {
  3830. /* This must be already handled by trace type inference */
  3831. ZEND_UNREACHABLE();
  3832. // SET_STACK_TYPE(stack, i, STACK_TYPE(parent_stack, i));
  3833. } else if ((info & MAY_BE_GUARD) != 0
  3834. && (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  3835. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  3836. || (trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET
  3837. && (opline-1)->result_type == IS_VAR
  3838. && EX_VAR_TO_NUM((opline-1)->result.var) == i))
  3839. && (ssa->vars[i].use_chain != -1
  3840. || (ssa->vars[i].phi_use_chain
  3841. && !(ssa->var_info[ssa->vars[i].phi_use_chain->ssa_var].type & MAY_BE_GUARD)))) {
  3842. /* Check loop-invariant variable type */
  3843. if (!zend_jit_type_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), concrete_type(info))) {
  3844. goto jit_failure;
  3845. }
  3846. info &= ~MAY_BE_GUARD;
  3847. ssa->var_info[i].type = info;
  3848. SET_STACK_TYPE(stack, i, concrete_type(info), 1);
  3849. } else if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER
  3850. && op_array->function_name
  3851. && i >= op_array->num_args) {
  3852. /* This must be already handled by trace type inference */
  3853. ZEND_UNREACHABLE();
  3854. // SET_STACK_TYPE(stack, i, IS_UNDEF, 1);
  3855. }
  3856. if ((info & MAY_BE_PACKED_GUARD) != 0
  3857. && (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  3858. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  3859. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET)
  3860. && (ssa->vars[i].use_chain != -1
  3861. || (ssa->vars[i].phi_use_chain
  3862. && !(ssa->var_info[ssa->vars[i].phi_use_chain->ssa_var].type & MAY_BE_PACKED_GUARD)))) {
  3863. if (!zend_jit_packed_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), info)) {
  3864. goto jit_failure;
  3865. }
  3866. info &= ~MAY_BE_PACKED_GUARD;
  3867. ssa->var_info[i].type = info;
  3868. }
  3869. }
  3870. if (parent_trace) {
  3871. /* Deoptimization */
  3872. if (!zend_jit_trace_deoptimization(&dasm_state,
  3873. zend_jit_traces[parent_trace].exit_info[exit_num].flags,
  3874. zend_jit_traces[parent_trace].exit_info[exit_num].opline,
  3875. parent_stack, parent_vars_count, ssa, stack, ra,
  3876. polymorphic_side_trace)) {
  3877. goto jit_failure;
  3878. }
  3879. }
  3880. if (ra
  3881. && trace_buffer->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  3882. && trace_buffer->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  3883. for (i = 0; i < last_var; i++) {
  3884. if (ra[i]
  3885. && (ra[i]->flags & ZREG_LOAD) != 0
  3886. && ra[i]->reg != stack[i].reg) {
  3887. if ((ssa->var_info[i].type & MAY_BE_GUARD) != 0) {
  3888. uint8_t op_type;
  3889. ssa->var_info[i].type &= ~MAY_BE_GUARD;
  3890. op_type = concrete_type(ssa->var_info[i].type);
  3891. if (!zend_jit_type_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), op_type)) {
  3892. goto jit_failure;
  3893. }
  3894. SET_STACK_TYPE(stack, i, op_type, 1);
  3895. }
  3896. SET_STACK_REG_EX(stack, i, ra[i]->reg, ZREG_LOAD);
  3897. if (!zend_jit_load_var(&dasm_state, ssa->var_info[i].type, i, ra[i]->reg)) {
  3898. goto jit_failure;
  3899. }
  3900. }
  3901. }
  3902. }
  3903. }
  3904. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  3905. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  3906. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  3907. zend_jit_label(&dasm_state, 0); /* start of of trace loop */
  3908. if (ra) {
  3909. zend_ssa_phi *phi = ssa->blocks[1].phis;
  3910. while (phi) {
  3911. zend_lifetime_interval *ival = ra[phi->ssa_var];
  3912. if (ival) {
  3913. if (ival->flags & ZREG_LOAD) {
  3914. uint32_t info = ssa->var_info[phi->ssa_var].type;
  3915. ZEND_ASSERT(ival->reg != ZREG_NONE);
  3916. if (info & MAY_BE_GUARD) {
  3917. if (!zend_jit_type_guard(&dasm_state, opline, EX_NUM_TO_VAR(phi->var), concrete_type(info))) {
  3918. goto jit_failure;
  3919. }
  3920. info &= ~MAY_BE_GUARD;
  3921. ssa->var_info[phi->ssa_var].type = info;
  3922. SET_STACK_TYPE(stack, phi->var, concrete_type(info), 1);
  3923. }
  3924. SET_STACK_REG_EX(stack, phi->var, ival->reg, ZREG_LOAD);
  3925. if (!zend_jit_load_var(&dasm_state, ssa->var_info[phi->ssa_var].type, ssa->vars[phi->ssa_var].var, ival->reg)) {
  3926. goto jit_failure;
  3927. }
  3928. } else if (ival->flags & ZREG_STORE) {
  3929. ZEND_ASSERT(ival->reg != ZREG_NONE);
  3930. SET_STACK_REG_EX(stack, phi->var, ival->reg, ZREG_STORE);
  3931. if (!zend_jit_store_var(&dasm_state, ssa->var_info[phi->ssa_var].type, ssa->vars[phi->ssa_var].var, ival->reg,
  3932. STACK_MEM_TYPE(stack, phi->var) != ssa->var_info[phi->ssa_var].type)) {
  3933. goto jit_failure;
  3934. }
  3935. } else {
  3936. /* Register has to be written back on side exit */
  3937. SET_STACK_REG(stack, phi->var, ival->reg);
  3938. }
  3939. }
  3940. phi = phi->next;
  3941. }
  3942. }
  3943. // if (trace_buffer->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  3944. // if (ra && zend_jit_trace_stack_needs_deoptimization(stack, op_array->last_var + op_array->T)) {
  3945. // uint32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
  3946. //
  3947. // timeout_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  3948. // if (!timeout_exit_addr) {
  3949. // goto jit_failure;
  3950. // }
  3951. // }
  3952. // }
  3953. if (ra && trace_buffer->stop != ZEND_JIT_TRACE_STOP_LOOP) {
  3954. int last_var = op_array->last_var;
  3955. if (trace_buffer->start != ZEND_JIT_TRACE_START_ENTER) {
  3956. last_var += op_array->T;
  3957. }
  3958. for (i = 0; i < last_var; i++) {
  3959. if (ra && ra[i] && (ra[i]->flags & ZREG_LOAD) != 0) {
  3960. SET_STACK_REG_EX(stack, i, ra[i]->reg, ZREG_LOAD);
  3961. if (!zend_jit_load_var(&dasm_state, ssa->var_info[i].type, i, ra[i]->reg)) {
  3962. goto jit_failure;
  3963. }
  3964. }
  3965. }
  3966. }
  3967. }
  3968. ssa_op = (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) ? ssa->ops : NULL;
  3969. for (;;p++) {
  3970. if (p->op == ZEND_JIT_TRACE_VM) {
  3971. uint8_t op1_type = p->op1_type;
  3972. uint8_t op2_type = p->op2_type;
  3973. uint8_t op3_type = p->op3_type;
  3974. uint8_t orig_op1_type = op1_type;
  3975. uint8_t orig_op2_type = op2_type;
  3976. uint8_t val_type = IS_UNKNOWN;
  3977. bool op1_indirect;
  3978. zend_class_entry *op1_ce = NULL;
  3979. zend_class_entry *op2_ce = NULL;
  3980. bool gen_handler;
  3981. opline = p->opline;
  3982. if (op1_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
  3983. op1_type = IS_UNKNOWN;
  3984. }
  3985. if (op1_type != IS_UNKNOWN) {
  3986. op1_type &= ~IS_TRACE_PACKED;
  3987. }
  3988. if (op2_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
  3989. op2_type = IS_UNKNOWN;
  3990. }
  3991. if (op3_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
  3992. op3_type = IS_UNKNOWN;
  3993. }
  3994. if ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE) {
  3995. op1_ce = (zend_class_entry*)(p+1)->ce;
  3996. p++;
  3997. }
  3998. if ((p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
  3999. op2_ce = (zend_class_entry*)(p+1)->ce;
  4000. p++;
  4001. }
  4002. if ((p+1)->op == ZEND_JIT_TRACE_VAL_INFO) {
  4003. val_type = (p+1)->op1_type;
  4004. p++;
  4005. }
  4006. frame_flags = 0;
  4007. switch (opline->opcode) {
  4008. case ZEND_INIT_FCALL:
  4009. case ZEND_INIT_FCALL_BY_NAME:
  4010. case ZEND_INIT_NS_FCALL_BY_NAME:
  4011. case ZEND_INIT_METHOD_CALL:
  4012. case ZEND_INIT_DYNAMIC_CALL:
  4013. case ZEND_INIT_STATIC_METHOD_CALL:
  4014. case ZEND_INIT_USER_CALL:
  4015. case ZEND_NEW:
  4016. frame->call_level++;
  4017. }
  4018. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
  4019. gen_handler = 0;
  4020. switch (opline->opcode) {
  4021. case ZEND_PRE_INC:
  4022. case ZEND_PRE_DEC:
  4023. case ZEND_POST_INC:
  4024. case ZEND_POST_DEC:
  4025. if (opline->op1_type != IS_CV) {
  4026. break;
  4027. }
  4028. op1_info = OP1_INFO();
  4029. CHECK_OP1_TRACE_TYPE();
  4030. if (!(op1_info & MAY_BE_LONG)) {
  4031. break;
  4032. }
  4033. if (opline->result_type != IS_UNUSED) {
  4034. res_use_info = zend_jit_trace_type_to_info(
  4035. STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)))
  4036. & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE);
  4037. res_info = RES_INFO();
  4038. res_addr = RES_REG_ADDR();
  4039. } else {
  4040. res_use_info = -1;
  4041. res_info = -1;
  4042. res_addr = 0;
  4043. }
  4044. op1_def_info = OP1_DEF_INFO();
  4045. if (op1_def_info & MAY_BE_GUARD
  4046. && !has_concrete_type(op1_def_info)) {
  4047. op1_def_info &= ~MAY_BE_GUARD;
  4048. }
  4049. if (!zend_jit_inc_dec(&dasm_state, opline,
  4050. op1_info, OP1_REG_ADDR(),
  4051. op1_def_info, OP1_DEF_REG_ADDR(),
  4052. res_use_info, res_info,
  4053. res_addr,
  4054. (op1_def_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa),
  4055. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  4056. goto jit_failure;
  4057. }
  4058. if ((op1_def_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)
  4059. && !(op1_info & MAY_BE_STRING)) {
  4060. ssa->var_info[ssa_op->op1_def].type &= ~MAY_BE_GUARD;
  4061. if (opline->result_type != IS_UNUSED) {
  4062. ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
  4063. }
  4064. }
  4065. if (opline->result_type != IS_UNUSED
  4066. && (res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)
  4067. && !(op1_info & MAY_BE_STRING)) {
  4068. ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
  4069. }
  4070. goto done;
  4071. case ZEND_BW_OR:
  4072. case ZEND_BW_AND:
  4073. case ZEND_BW_XOR:
  4074. case ZEND_SL:
  4075. case ZEND_SR:
  4076. case ZEND_MOD:
  4077. op1_info = OP1_INFO();
  4078. CHECK_OP1_TRACE_TYPE();
  4079. op2_info = OP2_INFO();
  4080. CHECK_OP2_TRACE_TYPE();
  4081. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  4082. break;
  4083. }
  4084. if (!(op1_info & MAY_BE_LONG)
  4085. || !(op2_info & MAY_BE_LONG)) {
  4086. break;
  4087. }
  4088. res_addr = RES_REG_ADDR();
  4089. if (Z_MODE(res_addr) != IS_REG
  4090. && zend_jit_trace_next_is_send_result(opline, p, frame)) {
  4091. send_result = 1;
  4092. res_use_info = -1;
  4093. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  4094. if (!zend_jit_reuse_ip(&dasm_state)) {
  4095. goto jit_failure;
  4096. }
  4097. } else {
  4098. res_use_info = zend_jit_trace_type_to_info(
  4099. STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)))
  4100. & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE);
  4101. }
  4102. res_info = RES_INFO();
  4103. if (!zend_jit_long_math(&dasm_state, opline,
  4104. op1_info, OP1_RANGE(), OP1_REG_ADDR(),
  4105. op2_info, OP2_RANGE(), OP2_REG_ADDR(),
  4106. res_use_info, res_info, res_addr,
  4107. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  4108. goto jit_failure;
  4109. }
  4110. goto done;
  4111. case ZEND_ADD:
  4112. case ZEND_SUB:
  4113. case ZEND_MUL:
  4114. // case ZEND_DIV: // TODO: check for division by zero ???
  4115. op1_info = OP1_INFO();
  4116. op1_addr = OP1_REG_ADDR();
  4117. op2_info = OP2_INFO();
  4118. op2_addr = OP2_REG_ADDR();
  4119. if (orig_op1_type != IS_UNKNOWN
  4120. && (orig_op1_type & IS_TRACE_REFERENCE)
  4121. && opline->op1_type == IS_CV
  4122. && (Z_MODE(op2_addr) != IS_REG || Z_REG(op2_addr) != ZREG_FCARG1)
  4123. && (orig_op2_type == IS_UNKNOWN || !(orig_op2_type & IS_TRACE_REFERENCE))) {
  4124. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4125. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  4126. goto jit_failure;
  4127. }
  4128. if (ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  4129. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  4130. }
  4131. } else {
  4132. CHECK_OP1_TRACE_TYPE();
  4133. }
  4134. if (orig_op2_type != IS_UNKNOWN
  4135. && (orig_op2_type & IS_TRACE_REFERENCE)
  4136. && opline->op2_type == IS_CV
  4137. && (Z_MODE(op1_addr) != IS_REG || Z_REG(op1_addr) != ZREG_FCARG1)
  4138. && (orig_op1_type == IS_UNKNOWN || !(orig_op1_type & IS_TRACE_REFERENCE))) {
  4139. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op2_type, &op2_info, &op2_addr,
  4140. !ssa->var_info[ssa_op->op2_use].guarded_reference, 1)) {
  4141. goto jit_failure;
  4142. }
  4143. if (ssa->vars[ssa_op->op2_use].alias == NO_ALIAS) {
  4144. ssa->var_info[ssa_op->op2_use].guarded_reference = 1;
  4145. }
  4146. } else {
  4147. CHECK_OP2_TRACE_TYPE();
  4148. }
  4149. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  4150. break;
  4151. }
  4152. if (opline->opcode == ZEND_ADD &&
  4153. (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
  4154. (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
  4155. /* pass */
  4156. } else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
  4157. !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  4158. break;
  4159. }
  4160. res_addr = RES_REG_ADDR();
  4161. if (Z_MODE(res_addr) != IS_REG
  4162. && zend_jit_trace_next_is_send_result(opline, p, frame)) {
  4163. send_result = 1;
  4164. res_use_info = -1;
  4165. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  4166. if (!zend_jit_reuse_ip(&dasm_state)) {
  4167. goto jit_failure;
  4168. }
  4169. } else {
  4170. res_use_info = zend_jit_trace_type_to_info(
  4171. STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)))
  4172. & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE);
  4173. }
  4174. res_info = RES_INFO();
  4175. if (opline->opcode == ZEND_ADD &&
  4176. (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
  4177. (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
  4178. if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op1_addr, op2_info, op2_addr, res_addr)) {
  4179. goto jit_failure;
  4180. }
  4181. } else {
  4182. if (!zend_jit_math(&dasm_state, opline,
  4183. op1_info, op1_addr,
  4184. op2_info, op2_addr,
  4185. res_use_info, res_info, res_addr,
  4186. (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa),
  4187. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  4188. goto jit_failure;
  4189. }
  4190. if (((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)
  4191. || (res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_DOUBLE|MAY_BE_GUARD))
  4192. && has_concrete_type(op1_info)
  4193. && has_concrete_type(op2_info)) {
  4194. ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
  4195. }
  4196. }
  4197. goto done;
  4198. case ZEND_CONCAT:
  4199. case ZEND_FAST_CONCAT:
  4200. op1_info = OP1_INFO();
  4201. CHECK_OP1_TRACE_TYPE();
  4202. op2_info = OP2_INFO();
  4203. CHECK_OP2_TRACE_TYPE();
  4204. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  4205. break;
  4206. }
  4207. if (!(op1_info & MAY_BE_STRING) ||
  4208. !(op2_info & MAY_BE_STRING)) {
  4209. break;
  4210. }
  4211. res_addr = RES_REG_ADDR();
  4212. if (zend_jit_trace_next_is_send_result(opline, p, frame)) {
  4213. send_result = 1;
  4214. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  4215. if (!zend_jit_reuse_ip(&dasm_state)) {
  4216. goto jit_failure;
  4217. }
  4218. }
  4219. if (!zend_jit_concat(&dasm_state, opline,
  4220. op1_info, op2_info, res_addr,
  4221. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  4222. goto jit_failure;
  4223. }
  4224. goto done;
  4225. case ZEND_ASSIGN_OP:
  4226. if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
  4227. break;
  4228. }
  4229. op1_info = OP1_INFO();
  4230. CHECK_OP1_TRACE_TYPE();
  4231. op2_info = OP2_INFO();
  4232. CHECK_OP2_TRACE_TYPE();
  4233. if (!zend_jit_supported_binary_op(
  4234. opline->extended_value, op1_info, op2_info)) {
  4235. break;
  4236. }
  4237. op1_def_info = OP1_DEF_INFO();
  4238. if (op1_def_info & MAY_BE_GUARD
  4239. && !has_concrete_type(op1_def_info)) {
  4240. op1_def_info &= ~MAY_BE_GUARD;
  4241. }
  4242. if (!zend_jit_assign_op(&dasm_state, opline,
  4243. op1_info, op1_def_info, OP1_RANGE(),
  4244. op2_info, OP2_RANGE(),
  4245. (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (op1_def_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa),
  4246. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  4247. goto jit_failure;
  4248. }
  4249. if ((op1_def_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)
  4250. && has_concrete_type(op1_info)
  4251. && has_concrete_type(op2_info)) {
  4252. ssa->var_info[ssa_op->op1_def].type &= ~MAY_BE_GUARD;
  4253. if (opline->result_type != IS_UNUSED) {
  4254. ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
  4255. }
  4256. }
  4257. goto done;
  4258. case ZEND_ASSIGN_DIM_OP:
  4259. if (opline->result_type != IS_UNUSED) {
  4260. break;
  4261. }
  4262. if (!zend_jit_supported_binary_op(
  4263. opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
  4264. break;
  4265. }
  4266. if (opline->op1_type == IS_CV
  4267. && (opline+1)->op1_type == IS_CV
  4268. && (opline+1)->op1.var == opline->op1.var) {
  4269. /* skip $a[x] += $a; */
  4270. break;
  4271. }
  4272. op1_info = OP1_INFO();
  4273. op1_addr = OP1_REG_ADDR();
  4274. if (opline->op1_type == IS_VAR) {
  4275. if (orig_op1_type != IS_UNKNOWN
  4276. && (orig_op1_type & IS_TRACE_INDIRECT)) {
  4277. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  4278. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  4279. goto jit_failure;
  4280. }
  4281. } else {
  4282. break;
  4283. }
  4284. }
  4285. if (orig_op1_type != IS_UNKNOWN
  4286. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  4287. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4288. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  4289. goto jit_failure;
  4290. }
  4291. if (opline->op1_type == IS_CV
  4292. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4293. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4294. }
  4295. } else {
  4296. CHECK_OP1_TRACE_TYPE();
  4297. }
  4298. op2_info = OP2_INFO();
  4299. CHECK_OP2_TRACE_TYPE();
  4300. op1_data_info = OP1_DATA_INFO();
  4301. CHECK_OP1_DATA_TRACE_TYPE();
  4302. op1_def_info = OP1_DEF_INFO();
  4303. if (!zend_jit_assign_dim_op(&dasm_state, opline,
  4304. op1_info, op1_def_info, op1_addr, op2_info,
  4305. op1_data_info, OP1_DATA_RANGE(), val_type,
  4306. zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
  4307. goto jit_failure;
  4308. }
  4309. goto done;
  4310. case ZEND_PRE_INC_OBJ:
  4311. case ZEND_PRE_DEC_OBJ:
  4312. case ZEND_POST_INC_OBJ:
  4313. case ZEND_POST_DEC_OBJ:
  4314. if (opline->op2_type != IS_CONST
  4315. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  4316. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  4317. break;
  4318. }
  4319. ce = NULL;
  4320. ce_is_instanceof = 0;
  4321. on_this = delayed_fetch_this = 0;
  4322. op1_indirect = 0;
  4323. if (opline->op1_type == IS_UNUSED) {
  4324. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  4325. ce = op_array->scope;
  4326. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  4327. op1_addr = 0;
  4328. on_this = 1;
  4329. } else {
  4330. if (ssa_op->op1_use >= 0) {
  4331. delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
  4332. }
  4333. op1_info = OP1_INFO();
  4334. if (!(op1_info & MAY_BE_OBJECT)) {
  4335. break;
  4336. }
  4337. op1_addr = OP1_REG_ADDR();
  4338. if (opline->op1_type == IS_VAR) {
  4339. if (orig_op1_type != IS_UNKNOWN
  4340. && (orig_op1_type & IS_TRACE_INDIRECT)) {
  4341. op1_indirect = 1;
  4342. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  4343. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  4344. goto jit_failure;
  4345. }
  4346. }
  4347. }
  4348. if (orig_op1_type != IS_UNKNOWN
  4349. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  4350. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4351. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  4352. goto jit_failure;
  4353. }
  4354. if (opline->op1_type == IS_CV
  4355. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4356. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4357. }
  4358. } else {
  4359. CHECK_OP1_TRACE_TYPE();
  4360. }
  4361. if (!(op1_info & MAY_BE_OBJECT)) {
  4362. break;
  4363. }
  4364. if (ssa->var_info && ssa->ops) {
  4365. if (ssa_op->op1_use >= 0) {
  4366. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  4367. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  4368. ce = op1_ssa->ce;
  4369. ce_is_instanceof = op1_ssa->is_instanceof;
  4370. }
  4371. }
  4372. }
  4373. if (delayed_fetch_this) {
  4374. on_this = 1;
  4375. } else if (ssa_op->op1_use >= 0 && ssa->vars[ssa_op->op1_use].definition >= 0) {
  4376. on_this = ssa_opcodes[ssa->vars[ssa_op->op1_use].definition]->opcode == ZEND_FETCH_THIS;
  4377. } else if (op_array_ssa->ops
  4378. && op_array_ssa->vars
  4379. && op_array_ssa->ops[opline-op_array->opcodes].op1_use >= 0
  4380. && op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition >= 0) {
  4381. on_this = op_array->opcodes[op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition].opcode == ZEND_FETCH_THIS;
  4382. }
  4383. }
  4384. if (!zend_jit_incdec_obj(&dasm_state, opline, op_array, ssa, ssa_op,
  4385. op1_info, op1_addr,
  4386. op1_indirect, ce, ce_is_instanceof, on_this, delayed_fetch_this, op1_ce,
  4387. val_type)) {
  4388. goto jit_failure;
  4389. }
  4390. goto done;
  4391. case ZEND_ASSIGN_OBJ_OP:
  4392. if (opline->result_type != IS_UNUSED) {
  4393. break;
  4394. }
  4395. if (opline->op2_type != IS_CONST
  4396. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  4397. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  4398. break;
  4399. }
  4400. if (opline->op1_type == IS_CV
  4401. && (opline+1)->op1_type == IS_CV
  4402. && (opline+1)->op1.var == opline->op1.var) {
  4403. /* skip $a->prop += $a; */
  4404. break;
  4405. }
  4406. if (!zend_jit_supported_binary_op(
  4407. opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
  4408. break;
  4409. }
  4410. ce = NULL;
  4411. ce_is_instanceof = 0;
  4412. on_this = delayed_fetch_this = 0;
  4413. op1_indirect = 0;
  4414. if (opline->op1_type == IS_UNUSED) {
  4415. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  4416. ce = op_array->scope;
  4417. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  4418. op1_addr = 0;
  4419. on_this = 1;
  4420. } else {
  4421. if (ssa_op->op1_use >= 0) {
  4422. delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
  4423. }
  4424. op1_info = OP1_INFO();
  4425. if (!(op1_info & MAY_BE_OBJECT)) {
  4426. break;
  4427. }
  4428. op1_addr = OP1_REG_ADDR();
  4429. if (opline->op1_type == IS_VAR) {
  4430. if (orig_op1_type != IS_UNKNOWN
  4431. && (orig_op1_type & IS_TRACE_INDIRECT)) {
  4432. op1_indirect = 1;
  4433. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  4434. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  4435. goto jit_failure;
  4436. }
  4437. }
  4438. }
  4439. if (orig_op1_type != IS_UNKNOWN
  4440. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  4441. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4442. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  4443. goto jit_failure;
  4444. }
  4445. if (opline->op1_type == IS_CV
  4446. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4447. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4448. }
  4449. } else {
  4450. CHECK_OP1_TRACE_TYPE();
  4451. }
  4452. if (!(op1_info & MAY_BE_OBJECT)) {
  4453. break;
  4454. }
  4455. if (ssa->var_info && ssa->ops) {
  4456. if (ssa_op->op1_use >= 0) {
  4457. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  4458. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  4459. ce = op1_ssa->ce;
  4460. ce_is_instanceof = op1_ssa->is_instanceof;
  4461. }
  4462. }
  4463. }
  4464. if (delayed_fetch_this) {
  4465. on_this = 1;
  4466. } else if (ssa_op->op1_use >= 0 && ssa->vars[ssa_op->op1_use].definition >= 0) {
  4467. on_this = ssa_opcodes[ssa->vars[ssa_op->op1_use].definition]->opcode == ZEND_FETCH_THIS;
  4468. } else if (op_array_ssa->ops
  4469. && op_array_ssa->vars
  4470. && op_array_ssa->ops[opline-op_array->opcodes].op1_use >= 0
  4471. && op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition >= 0) {
  4472. on_this = op_array->opcodes[op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition].opcode == ZEND_FETCH_THIS;
  4473. }
  4474. }
  4475. op1_data_info = OP1_DATA_INFO();
  4476. CHECK_OP1_DATA_TRACE_TYPE();
  4477. if (!zend_jit_assign_obj_op(&dasm_state, opline, op_array, ssa, ssa_op,
  4478. op1_info, op1_addr, op1_data_info, OP1_DATA_RANGE(),
  4479. op1_indirect, ce, ce_is_instanceof, on_this, delayed_fetch_this, op1_ce,
  4480. val_type)) {
  4481. goto jit_failure;
  4482. }
  4483. goto done;
  4484. case ZEND_ASSIGN_OBJ:
  4485. if (opline->op2_type != IS_CONST
  4486. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  4487. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  4488. break;
  4489. }
  4490. ce = NULL;
  4491. ce_is_instanceof = 0;
  4492. on_this = delayed_fetch_this = 0;
  4493. op1_indirect = 0;
  4494. if (opline->op1_type == IS_UNUSED) {
  4495. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  4496. ce = op_array->scope;
  4497. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  4498. op1_addr = 0;
  4499. on_this = 1;
  4500. } else {
  4501. if (ssa_op->op1_use >= 0) {
  4502. delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
  4503. }
  4504. op1_info = OP1_INFO();
  4505. if (!(op1_info & MAY_BE_OBJECT)) {
  4506. break;
  4507. }
  4508. op1_addr = OP1_REG_ADDR();
  4509. if (opline->op1_type == IS_VAR) {
  4510. if (orig_op1_type != IS_UNKNOWN
  4511. && (orig_op1_type & IS_TRACE_INDIRECT)) {
  4512. op1_indirect = 1;
  4513. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  4514. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  4515. goto jit_failure;
  4516. }
  4517. }
  4518. }
  4519. if (orig_op1_type != IS_UNKNOWN
  4520. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  4521. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4522. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  4523. goto jit_failure;
  4524. }
  4525. if (opline->op1_type == IS_CV
  4526. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4527. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4528. }
  4529. } else {
  4530. CHECK_OP1_TRACE_TYPE();
  4531. }
  4532. if (!(op1_info & MAY_BE_OBJECT)) {
  4533. break;
  4534. }
  4535. if (ssa->var_info && ssa->ops) {
  4536. if (ssa_op->op1_use >= 0) {
  4537. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  4538. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  4539. ce = op1_ssa->ce;
  4540. ce_is_instanceof = op1_ssa->is_instanceof;
  4541. }
  4542. }
  4543. }
  4544. if (delayed_fetch_this) {
  4545. on_this = 1;
  4546. } else if (ssa_op->op1_use >= 0 && ssa->vars[ssa_op->op1_use].definition >= 0) {
  4547. on_this = ssa_opcodes[ssa->vars[ssa_op->op1_use].definition]->opcode == ZEND_FETCH_THIS;
  4548. } else if (op_array_ssa->ops
  4549. && op_array_ssa->vars
  4550. && op_array_ssa->ops[opline-op_array->opcodes].op1_use >= 0
  4551. && op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition >= 0) {
  4552. on_this = op_array->opcodes[op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition].opcode == ZEND_FETCH_THIS;
  4553. }
  4554. }
  4555. op1_data_info = OP1_DATA_INFO();
  4556. CHECK_OP1_DATA_TRACE_TYPE();
  4557. if (!zend_jit_assign_obj(&dasm_state, opline, op_array, ssa, ssa_op,
  4558. op1_info, op1_addr, op1_data_info,
  4559. op1_indirect, ce, ce_is_instanceof, on_this, delayed_fetch_this, op1_ce,
  4560. val_type,
  4561. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  4562. goto jit_failure;
  4563. }
  4564. if ((opline+1)->op1_type == IS_CV
  4565. && (ssa_op+1)->op1_def >= 0
  4566. && ssa->vars[(ssa_op+1)->op1_def].alias == NO_ALIAS) {
  4567. ssa->var_info[(ssa_op+1)->op1_def].guarded_reference = ssa->var_info[(ssa_op+1)->op1_use].guarded_reference;
  4568. }
  4569. goto done;
  4570. case ZEND_ASSIGN_DIM:
  4571. op1_info = OP1_INFO();
  4572. op1_addr = OP1_REG_ADDR();
  4573. if (opline->op1_type == IS_CV
  4574. && (opline+1)->op1_type == IS_CV
  4575. && (opline+1)->op1.var == opline->op1.var) {
  4576. /* skip $a[x] = $a; */
  4577. break;
  4578. }
  4579. if (opline->op1_type == IS_VAR) {
  4580. if (orig_op1_type != IS_UNKNOWN
  4581. && (orig_op1_type & IS_TRACE_INDIRECT)
  4582. && opline->result_type == IS_UNUSED) {
  4583. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  4584. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  4585. goto jit_failure;
  4586. }
  4587. } else {
  4588. break;
  4589. }
  4590. }
  4591. if (orig_op1_type != IS_UNKNOWN
  4592. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  4593. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4594. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  4595. goto jit_failure;
  4596. }
  4597. if (opline->op1_type == IS_CV
  4598. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4599. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4600. }
  4601. } else {
  4602. CHECK_OP1_TRACE_TYPE();
  4603. }
  4604. op2_info = OP2_INFO();
  4605. CHECK_OP2_TRACE_TYPE();
  4606. op1_data_info = OP1_DATA_INFO();
  4607. CHECK_OP1_DATA_TRACE_TYPE();
  4608. if (!zend_jit_assign_dim(&dasm_state, opline,
  4609. op1_info, op1_addr, op2_info, op1_data_info, val_type,
  4610. zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
  4611. goto jit_failure;
  4612. }
  4613. if ((opline+1)->op1_type == IS_CV
  4614. && (ssa_op+1)->op1_def >= 0
  4615. && ssa->vars[(ssa_op+1)->op1_def].alias == NO_ALIAS) {
  4616. ssa->var_info[(ssa_op+1)->op1_def].guarded_reference = ssa->var_info[(ssa_op+1)->op1_use].guarded_reference;
  4617. }
  4618. goto done;
  4619. case ZEND_ASSIGN:
  4620. if (opline->op1_type != IS_CV) {
  4621. break;
  4622. }
  4623. op2_addr = OP2_REG_ADDR();
  4624. op2_info = OP2_INFO();
  4625. if (ra
  4626. && ssa_op->op2_def >= 0
  4627. && (!ssa->vars[ssa_op->op2_def].no_val
  4628. || (zend_jit_trace_type_to_info(STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var))) & MAY_BE_ANY) !=
  4629. (op2_info & MAY_BE_ANY))) {
  4630. op2_def_addr = OP2_DEF_REG_ADDR();
  4631. } else {
  4632. op2_def_addr = op2_addr;
  4633. }
  4634. CHECK_OP2_TRACE_TYPE();
  4635. op1_info = OP1_INFO();
  4636. op1_def_info = OP1_DEF_INFO();
  4637. if (op1_type != IS_UNKNOWN && (op1_info & MAY_BE_GUARD)) {
  4638. if (op1_type < IS_STRING
  4639. && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) != (op1_def_info & (MAY_BE_ANY|MAY_BE_UNDEF))) {
  4640. if (!zend_jit_scalar_type_guard(&dasm_state, opline, opline->op1.var)) {
  4641. goto jit_failure;
  4642. }
  4643. op1_info &= ~(MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF|MAY_BE_GUARD);
  4644. } else {
  4645. CHECK_OP1_TRACE_TYPE();
  4646. }
  4647. }
  4648. op1_addr = OP1_REG_ADDR();
  4649. op1_def_addr = OP1_DEF_REG_ADDR();
  4650. if (Z_MODE(op1_def_addr) != IS_REG &&
  4651. STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var)) !=
  4652. STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var))) {
  4653. /* type may be not set */
  4654. op1_info |= MAY_BE_NULL;
  4655. }
  4656. if (orig_op1_type != IS_UNKNOWN) {
  4657. if (orig_op1_type & IS_TRACE_REFERENCE) {
  4658. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  4659. !ssa->var_info[ssa_op->op1_use].guarded_reference, 0)) {
  4660. goto jit_failure;
  4661. }
  4662. if (opline->op1_type == IS_CV
  4663. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4664. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4665. }
  4666. if (opline->result_type == IS_UNUSED) {
  4667. res_addr = 0;
  4668. } else {
  4669. res_addr = RES_REG_ADDR();
  4670. }
  4671. if (!zend_jit_assign_to_typed_ref(&dasm_state, opline, opline->op2_type, op2_addr, res_addr, 1)) {
  4672. goto jit_failure;
  4673. }
  4674. op1_def_addr = op1_addr;
  4675. op1_def_info &= ~MAY_BE_REF;
  4676. } else if (op1_info & MAY_BE_REF) {
  4677. if (!zend_jit_noref_guard(&dasm_state, opline, op1_addr)) {
  4678. goto jit_failure;
  4679. }
  4680. op1_info &= ~MAY_BE_REF;
  4681. op1_def_info &= ~MAY_BE_REF;
  4682. }
  4683. }
  4684. if (opline->result_type == IS_UNUSED) {
  4685. res_addr = 0;
  4686. res_info = -1;
  4687. } else {
  4688. res_addr = RES_REG_ADDR();
  4689. res_info = RES_INFO();
  4690. if (Z_MODE(res_addr) != IS_REG
  4691. && zend_jit_trace_next_is_send_result(opline, p, frame)) {
  4692. send_result = 1;
  4693. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  4694. if (!zend_jit_reuse_ip(&dasm_state)) {
  4695. goto jit_failure;
  4696. }
  4697. }
  4698. }
  4699. if (!zend_jit_assign(&dasm_state, opline,
  4700. op1_info, op1_addr,
  4701. op1_def_info, op1_def_addr,
  4702. op2_info, op2_addr, op2_def_addr,
  4703. res_info, res_addr,
  4704. zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
  4705. goto jit_failure;
  4706. }
  4707. if (opline->op2_type == IS_CV
  4708. && ssa_op->op2_def >= 0
  4709. && ssa->vars[ssa_op->op2_def].alias == NO_ALIAS) {
  4710. ssa->var_info[ssa_op->op2_def].guarded_reference = ssa->var_info[ssa_op->op2_use].guarded_reference;
  4711. }
  4712. goto done;
  4713. case ZEND_CAST:
  4714. if (opline->extended_value != op1_type) {
  4715. break;
  4716. }
  4717. ZEND_FALLTHROUGH;
  4718. case ZEND_QM_ASSIGN:
  4719. op1_addr = OP1_REG_ADDR();
  4720. if (ra
  4721. && ssa_op->op1_def >= 0
  4722. && !ssa->vars[ssa_op->op1_def].no_val) {
  4723. op1_def_addr = OP1_DEF_REG_ADDR();
  4724. } else {
  4725. op1_def_addr = op1_addr;
  4726. }
  4727. op1_info = OP1_INFO();
  4728. CHECK_OP1_TRACE_TYPE();
  4729. res_info = RES_INFO();
  4730. res_use_info = zend_jit_trace_type_to_info(
  4731. STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)))
  4732. & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE);
  4733. res_addr = RES_REG_ADDR();
  4734. if (Z_MODE(res_addr) != IS_REG &&
  4735. STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)) !=
  4736. STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var))) {
  4737. /* type may be not set */
  4738. res_use_info |= MAY_BE_NULL;
  4739. }
  4740. if (!zend_jit_qm_assign(&dasm_state, opline,
  4741. op1_info, op1_addr, op1_def_addr,
  4742. res_use_info, res_info, res_addr)) {
  4743. goto jit_failure;
  4744. }
  4745. if (opline->op1_type == IS_CV
  4746. && ssa_op->op1_def >= 0
  4747. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4748. ssa->var_info[ssa_op->op1_def].guarded_reference = ssa->var_info[ssa_op->op1_use].guarded_reference;
  4749. }
  4750. goto done;
  4751. case ZEND_INIT_FCALL:
  4752. case ZEND_INIT_FCALL_BY_NAME:
  4753. case ZEND_INIT_NS_FCALL_BY_NAME:
  4754. frame_flags = TRACE_FRAME_MASK_NESTED;
  4755. if (!zend_jit_init_fcall(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, peek_checked_stack - checked_stack)) {
  4756. goto jit_failure;
  4757. }
  4758. goto done;
  4759. case ZEND_SEND_VAL:
  4760. case ZEND_SEND_VAL_EX:
  4761. if (opline->op2_type == IS_CONST) {
  4762. /* Named parameters not supported in JIT */
  4763. break;
  4764. }
  4765. if (opline->opcode == ZEND_SEND_VAL_EX
  4766. && opline->op2.num > MAX_ARG_FLAG_NUM) {
  4767. break;
  4768. }
  4769. op1_info = OP1_INFO();
  4770. CHECK_OP1_TRACE_TYPE();
  4771. if (!zend_jit_send_val(&dasm_state, opline,
  4772. op1_info, OP1_REG_ADDR())) {
  4773. goto jit_failure;
  4774. }
  4775. if (frame->call && frame->call->func) {
  4776. if (opline->op1_type == IS_CONST) {
  4777. zend_jit_trace_send_type(opline, frame->call, Z_TYPE_P(RT_CONSTANT(opline, opline->op1)));
  4778. } else if (op1_type != IS_UNKNOWN) {
  4779. if (op1_type == IS_UNDEF) {
  4780. op1_type = IS_NULL;
  4781. }
  4782. zend_jit_trace_send_type(opline, frame->call, op1_type);
  4783. }
  4784. }
  4785. goto done;
  4786. case ZEND_SEND_REF:
  4787. if (opline->op2_type == IS_CONST) {
  4788. /* Named parameters not supported in JIT */
  4789. break;
  4790. }
  4791. op1_info = OP1_INFO();
  4792. if (!zend_jit_send_ref(&dasm_state, opline, op_array,
  4793. op1_info, 0)) {
  4794. goto jit_failure;
  4795. }
  4796. if (opline->op1_type == IS_CV
  4797. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4798. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  4799. }
  4800. goto done;
  4801. case ZEND_SEND_VAR:
  4802. case ZEND_SEND_VAR_EX:
  4803. case ZEND_SEND_VAR_NO_REF:
  4804. case ZEND_SEND_VAR_NO_REF_EX:
  4805. case ZEND_SEND_FUNC_ARG:
  4806. if (opline->op2_type == IS_CONST) {
  4807. /* Named parameters not supported in JIT */
  4808. break;
  4809. }
  4810. if ((opline->opcode == ZEND_SEND_VAR_EX
  4811. || opline->opcode == ZEND_SEND_VAR_NO_REF_EX)
  4812. && opline->op2.num > MAX_ARG_FLAG_NUM) {
  4813. break;
  4814. }
  4815. op1_addr = OP1_REG_ADDR();
  4816. if (ra
  4817. && ssa_op->op1_def >= 0
  4818. && !ssa->vars[ssa_op->op1_def].no_val) {
  4819. op1_def_addr = OP1_DEF_REG_ADDR();
  4820. } else {
  4821. op1_def_addr = op1_addr;
  4822. }
  4823. op1_info = OP1_INFO();
  4824. CHECK_OP1_TRACE_TYPE();
  4825. if (!zend_jit_send_var(&dasm_state, opline, op_array,
  4826. op1_info, op1_addr, op1_def_addr)) {
  4827. goto jit_failure;
  4828. }
  4829. if (opline->op1_type == IS_CV
  4830. && ssa_op->op1_def >= 0
  4831. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  4832. ssa->var_info[ssa_op->op1_def].guarded_reference = ssa->var_info[ssa_op->op1_use].guarded_reference;
  4833. }
  4834. if (frame->call && frame->call->func) {
  4835. if ((opline->opcode == ZEND_SEND_VAR_EX
  4836. || opline->opcode == ZEND_SEND_FUNC_ARG)
  4837. && ARG_SHOULD_BE_SENT_BY_REF(frame->call->func, opline->op2.num)) {
  4838. goto done;
  4839. }
  4840. if (op1_type != IS_UNKNOWN) {
  4841. if (op1_type == IS_UNDEF) {
  4842. op1_type = IS_NULL;
  4843. }
  4844. zend_jit_trace_send_type(opline, frame->call, op1_type);
  4845. }
  4846. }
  4847. goto done;
  4848. case ZEND_CHECK_FUNC_ARG:
  4849. if (!JIT_G(current_frame)
  4850. || !JIT_G(current_frame)->call
  4851. || !JIT_G(current_frame)->call->func) {
  4852. break;
  4853. }
  4854. if (opline->op2_type == IS_CONST
  4855. || opline->op2.num > MAX_ARG_FLAG_NUM) {
  4856. /* Named parameters not supported in JIT */
  4857. TRACE_FRAME_SET_LAST_SEND_UNKNOWN(JIT_G(current_frame)->call);
  4858. break;
  4859. }
  4860. if (!zend_jit_check_func_arg(&dasm_state, opline)) {
  4861. goto jit_failure;
  4862. }
  4863. goto done;
  4864. case ZEND_CHECK_UNDEF_ARGS:
  4865. if (JIT_G(current_frame)
  4866. && JIT_G(current_frame)->call) {
  4867. TRACE_FRAME_SET_UNKNOWN_NUM_ARGS(JIT_G(current_frame)->call);
  4868. }
  4869. if (!zend_jit_check_undef_args(&dasm_state, opline)) {
  4870. goto jit_failure;
  4871. }
  4872. goto done;
  4873. case ZEND_DO_UCALL:
  4874. case ZEND_DO_ICALL:
  4875. case ZEND_DO_FCALL_BY_NAME:
  4876. case ZEND_DO_FCALL:
  4877. if (!zend_jit_do_fcall(&dasm_state, opline, op_array, op_array_ssa, frame->call_level, -1, p + 1)) {
  4878. goto jit_failure;
  4879. }
  4880. goto done;
  4881. case ZEND_IS_EQUAL:
  4882. case ZEND_IS_NOT_EQUAL:
  4883. case ZEND_IS_SMALLER:
  4884. case ZEND_IS_SMALLER_OR_EQUAL:
  4885. case ZEND_CASE:
  4886. op1_info = OP1_INFO();
  4887. op2_info = OP2_INFO();
  4888. skip_comparison =
  4889. ssa_op != ssa->ops &&
  4890. (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG &&
  4891. (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG &&
  4892. zend_jit_may_skip_comparison(opline, ssa_op, ssa, ssa_opcodes, op_array);
  4893. CHECK_OP1_TRACE_TYPE();
  4894. CHECK_OP2_TRACE_TYPE();
  4895. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  4896. bool exit_if_true = 0;
  4897. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  4898. uint32_t exit_point;
  4899. if (ra) {
  4900. zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra);
  4901. }
  4902. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  4903. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  4904. if (!exit_addr) {
  4905. goto jit_failure;
  4906. }
  4907. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  4908. if (!zend_jit_cmp(&dasm_state, opline,
  4909. op1_info, OP1_RANGE(), OP1_REG_ADDR(),
  4910. op2_info, OP2_RANGE(), OP2_REG_ADDR(),
  4911. RES_REG_ADDR(),
  4912. zend_may_throw(opline, ssa_op, op_array, ssa),
  4913. smart_branch_opcode, -1, -1, exit_addr, skip_comparison)) {
  4914. goto jit_failure;
  4915. }
  4916. zend_jit_trace_update_condition_ranges(opline, ssa_op, op_array, ssa, exit_if_true);
  4917. } else {
  4918. smart_branch_opcode = 0;
  4919. exit_addr = NULL;
  4920. if (!zend_jit_cmp(&dasm_state, opline,
  4921. op1_info, OP1_RANGE(), OP1_REG_ADDR(),
  4922. op2_info, OP2_RANGE(), OP2_REG_ADDR(),
  4923. RES_REG_ADDR(),
  4924. zend_may_throw(opline, ssa_op, op_array, ssa),
  4925. smart_branch_opcode, -1, -1, exit_addr, skip_comparison)) {
  4926. goto jit_failure;
  4927. }
  4928. }
  4929. goto done;
  4930. case ZEND_IS_IDENTICAL:
  4931. case ZEND_IS_NOT_IDENTICAL:
  4932. case ZEND_CASE_STRICT:
  4933. op1_info = OP1_INFO();
  4934. op2_info = OP2_INFO();
  4935. skip_comparison =
  4936. ssa_op != ssa->ops &&
  4937. (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG &&
  4938. (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG &&
  4939. zend_jit_may_skip_comparison(opline, ssa_op, ssa, ssa_opcodes, op_array);
  4940. CHECK_OP1_TRACE_TYPE();
  4941. CHECK_OP2_TRACE_TYPE();
  4942. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  4943. bool exit_if_true = 0;
  4944. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  4945. uint32_t exit_point;
  4946. if (ra) {
  4947. zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra);
  4948. }
  4949. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  4950. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  4951. if (!exit_addr) {
  4952. goto jit_failure;
  4953. }
  4954. if (opline->opcode == ZEND_IS_NOT_IDENTICAL) {
  4955. exit_if_true = !exit_if_true;
  4956. }
  4957. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  4958. if (!zend_jit_identical(&dasm_state, opline,
  4959. op1_info, OP1_RANGE(), OP1_REG_ADDR(),
  4960. op2_info, OP2_RANGE(), OP2_REG_ADDR(),
  4961. RES_REG_ADDR(),
  4962. zend_may_throw(opline, ssa_op, op_array, ssa),
  4963. smart_branch_opcode, -1, -1, exit_addr, skip_comparison)) {
  4964. goto jit_failure;
  4965. }
  4966. zend_jit_trace_update_condition_ranges(opline, ssa_op, op_array, ssa, exit_if_true);
  4967. } else {
  4968. smart_branch_opcode = 0;
  4969. exit_addr = NULL;
  4970. if (!zend_jit_identical(&dasm_state, opline,
  4971. op1_info, OP1_RANGE(), OP1_REG_ADDR(),
  4972. op2_info, OP2_RANGE(), OP2_REG_ADDR(),
  4973. RES_REG_ADDR(),
  4974. zend_may_throw(opline, ssa_op, op_array, ssa),
  4975. smart_branch_opcode, -1, -1, exit_addr, skip_comparison)) {
  4976. goto jit_failure;
  4977. }
  4978. }
  4979. goto done;
  4980. case ZEND_DEFINED:
  4981. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  4982. bool exit_if_true = 0;
  4983. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  4984. uint32_t exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  4985. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  4986. if (!exit_addr) {
  4987. goto jit_failure;
  4988. }
  4989. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  4990. } else {
  4991. smart_branch_opcode = 0;
  4992. exit_addr = NULL;
  4993. }
  4994. if (!zend_jit_defined(&dasm_state, opline, smart_branch_opcode, -1, -1, exit_addr)) {
  4995. goto jit_failure;
  4996. }
  4997. goto done;
  4998. case ZEND_TYPE_CHECK:
  4999. if (opline->extended_value == MAY_BE_RESOURCE) {
  5000. // TODO: support for is_resource() ???
  5001. break;
  5002. }
  5003. op1_info = OP1_INFO();
  5004. CHECK_OP1_TRACE_TYPE();
  5005. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  5006. bool exit_if_true = 0;
  5007. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  5008. uint32_t exit_point;
  5009. if (ra) {
  5010. zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra);
  5011. }
  5012. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5013. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5014. if (!exit_addr) {
  5015. goto jit_failure;
  5016. }
  5017. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  5018. } else {
  5019. smart_branch_opcode = 0;
  5020. exit_addr = NULL;
  5021. }
  5022. if (!zend_jit_type_check(&dasm_state, opline, op1_info, smart_branch_opcode, -1, -1, exit_addr)) {
  5023. goto jit_failure;
  5024. }
  5025. goto done;
  5026. case ZEND_RETURN:
  5027. op1_info = OP1_INFO();
  5028. CHECK_OP1_TRACE_TYPE();
  5029. if (opline->op1_type == IS_CONST) {
  5030. res_type = Z_TYPE_P(RT_CONSTANT(opline, opline->op1));
  5031. } else if (op1_type != IS_UNKNOWN) {
  5032. res_type = op1_type;
  5033. }
  5034. if (op_array->type == ZEND_EVAL_CODE
  5035. // TODO: support for top-level code
  5036. || !op_array->function_name
  5037. // TODO: support for IS_UNDEF ???
  5038. || (op1_info & MAY_BE_UNDEF)) {
  5039. if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) {
  5040. goto jit_failure;
  5041. }
  5042. } else {
  5043. int j;
  5044. int may_throw = 0;
  5045. bool left_frame = 0;
  5046. if (!zend_jit_return(&dasm_state, opline, op_array,
  5047. op1_info, OP1_REG_ADDR())) {
  5048. goto jit_failure;
  5049. }
  5050. if (op_array->last_var > 100) {
  5051. /* To many CVs to unroll */
  5052. if (!zend_jit_free_cvs(&dasm_state)) {
  5053. goto jit_failure;
  5054. }
  5055. left_frame = 1;
  5056. }
  5057. if (!left_frame) {
  5058. for (j = 0 ; j < op_array->last_var; j++) {
  5059. uint32_t info;
  5060. zend_uchar type;
  5061. info = zend_ssa_cv_info(op_array, op_array_ssa, j);
  5062. type = STACK_TYPE(stack, j);
  5063. info = zend_jit_trace_type_to_info_ex(type, info);
  5064. if (opline->op1_type == IS_CV
  5065. && EX_VAR_TO_NUM(opline->op1.var) == j
  5066. && !(op1_info & (MAY_BE_REF|MAY_BE_OBJECT))) {
  5067. if (JIT_G(current_frame)
  5068. && TRACE_FRAME_IS_RETURN_VALUE_USED(JIT_G(current_frame))) {
  5069. continue;
  5070. } else {
  5071. info |= MAY_BE_NULL;
  5072. }
  5073. }
  5074. if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
  5075. if (!left_frame) {
  5076. left_frame = 1;
  5077. if (!zend_jit_leave_frame(&dasm_state)) {
  5078. goto jit_failure;
  5079. }
  5080. }
  5081. if (!zend_jit_free_cv(&dasm_state, info, j)) {
  5082. goto jit_failure;
  5083. }
  5084. if (info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_RESOURCE)) {
  5085. if (info & MAY_BE_RC1) {
  5086. may_throw = 1;
  5087. }
  5088. }
  5089. }
  5090. }
  5091. }
  5092. if (!zend_jit_leave_func(&dasm_state, op_array, opline, op1_info, left_frame,
  5093. p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM],
  5094. (op_array_ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0, may_throw)) {
  5095. goto jit_failure;
  5096. }
  5097. }
  5098. goto done;
  5099. case ZEND_BOOL:
  5100. case ZEND_BOOL_NOT:
  5101. op1_info = OP1_INFO();
  5102. CHECK_OP1_TRACE_TYPE();
  5103. if (!zend_jit_bool_jmpznz(&dasm_state, opline,
  5104. op1_info, OP1_REG_ADDR(), RES_REG_ADDR(),
  5105. -1, -1,
  5106. zend_may_throw(opline, ssa_op, op_array, ssa),
  5107. opline->opcode, NULL)) {
  5108. goto jit_failure;
  5109. }
  5110. goto done;
  5111. case ZEND_JMPZ:
  5112. case ZEND_JMPNZ:
  5113. case ZEND_JMPZNZ:
  5114. case ZEND_JMPZ_EX:
  5115. case ZEND_JMPNZ_EX:
  5116. op1_info = OP1_INFO();
  5117. CHECK_OP1_TRACE_TYPE();
  5118. if ((p+1)->op == ZEND_JIT_TRACE_VM || (p+1)->op == ZEND_JIT_TRACE_END) {
  5119. const zend_op *exit_opline = NULL;
  5120. uint32_t exit_point;
  5121. if ((p+1)->opline == OP_JMP_ADDR(opline, opline->op2)) {
  5122. /* taken branch */
  5123. if (opline->opcode == ZEND_JMPNZ_EX) {
  5124. smart_branch_opcode = ZEND_JMPZ_EX;
  5125. } else if (opline->opcode == ZEND_JMPZ_EX) {
  5126. smart_branch_opcode = ZEND_JMPNZ_EX;
  5127. } else if (opline->opcode == ZEND_JMPNZ) {
  5128. smart_branch_opcode = ZEND_JMPZ;
  5129. } else {
  5130. smart_branch_opcode = ZEND_JMPNZ;
  5131. }
  5132. exit_opline = (opline->opcode == ZEND_JMPZNZ) ?
  5133. ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) :
  5134. opline + 1;
  5135. } else if (opline->opcode == ZEND_JMPZNZ) {
  5136. ZEND_ASSERT((p+1)->opline == ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value));
  5137. smart_branch_opcode = ZEND_JMPZ;
  5138. exit_opline = OP_JMP_ADDR(opline, opline->op2);
  5139. } else if ((p+1)->opline == opline + 1) {
  5140. /* not taken branch */
  5141. smart_branch_opcode = opline->opcode;
  5142. exit_opline = OP_JMP_ADDR(opline, opline->op2);
  5143. } else {
  5144. ZEND_UNREACHABLE();
  5145. }
  5146. if (ra) {
  5147. zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra);
  5148. }
  5149. if (!(op1_info & MAY_BE_GUARD)
  5150. && has_concrete_type(op1_info)
  5151. && concrete_type(op1_info) <= IS_TRUE) {
  5152. /* unconditional branch */
  5153. exit_addr = NULL;
  5154. } else if (opline->result_type == IS_TMP_VAR) {
  5155. zend_jit_trace_stack *stack = JIT_G(current_frame)->stack;
  5156. uint32_t old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var));
  5157. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_UNKNOWN, 1);
  5158. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5159. SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_info);
  5160. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5161. if (!exit_addr) {
  5162. goto jit_failure;
  5163. }
  5164. } else {
  5165. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5166. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5167. if (!exit_addr) {
  5168. goto jit_failure;
  5169. }
  5170. }
  5171. } else {
  5172. ZEND_UNREACHABLE();
  5173. }
  5174. if (opline->result_type == IS_UNDEF) {
  5175. res_addr = 0;
  5176. } else {
  5177. res_addr = RES_REG_ADDR();
  5178. }
  5179. if (!zend_jit_bool_jmpznz(&dasm_state, opline,
  5180. op1_info, OP1_REG_ADDR(), res_addr,
  5181. -1, -1,
  5182. zend_may_throw(opline, ssa_op, op_array, ssa),
  5183. smart_branch_opcode, exit_addr)) {
  5184. goto jit_failure;
  5185. }
  5186. goto done;
  5187. case ZEND_ISSET_ISEMPTY_CV:
  5188. if ((opline->extended_value & ZEND_ISEMPTY)) {
  5189. // TODO: support for empty() ???
  5190. break;
  5191. }
  5192. op1_info = OP1_INFO();
  5193. op1_addr = OP1_REG_ADDR();
  5194. if (orig_op1_type != IS_UNKNOWN
  5195. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  5196. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5197. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5198. goto jit_failure;
  5199. }
  5200. if (opline->op1_type == IS_CV
  5201. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5202. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  5203. }
  5204. } else {
  5205. CHECK_OP1_TRACE_TYPE();
  5206. }
  5207. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  5208. bool exit_if_true = 0;
  5209. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  5210. uint32_t exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5211. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5212. if (!exit_addr) {
  5213. goto jit_failure;
  5214. }
  5215. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  5216. } else {
  5217. smart_branch_opcode = 0;
  5218. exit_addr = NULL;
  5219. }
  5220. if (!zend_jit_isset_isempty_cv(&dasm_state, opline,
  5221. op1_info, op1_addr,
  5222. smart_branch_opcode, -1, -1, exit_addr)) {
  5223. goto jit_failure;
  5224. }
  5225. goto done;
  5226. case ZEND_IN_ARRAY:
  5227. if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
  5228. break;
  5229. }
  5230. op1_info = OP1_INFO();
  5231. op1_addr = OP1_REG_ADDR();
  5232. CHECK_OP1_TRACE_TYPE();
  5233. if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_STRING) {
  5234. break;
  5235. }
  5236. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  5237. bool exit_if_true = 0;
  5238. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  5239. uint32_t exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5240. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5241. if (!exit_addr) {
  5242. goto jit_failure;
  5243. }
  5244. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  5245. } else {
  5246. smart_branch_opcode = 0;
  5247. exit_addr = NULL;
  5248. }
  5249. if (!zend_jit_in_array(&dasm_state, opline,
  5250. op1_info, op1_addr,
  5251. smart_branch_opcode, -1, -1, exit_addr)) {
  5252. goto jit_failure;
  5253. }
  5254. goto done;
  5255. case ZEND_FETCH_DIM_FUNC_ARG:
  5256. if (!JIT_G(current_frame)
  5257. || !JIT_G(current_frame)->call
  5258. || !JIT_G(current_frame)->call->func
  5259. || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
  5260. break;
  5261. }
  5262. ZEND_FALLTHROUGH;
  5263. case ZEND_FETCH_DIM_R:
  5264. case ZEND_FETCH_DIM_IS:
  5265. case ZEND_FETCH_LIST_R:
  5266. op1_info = OP1_INFO();
  5267. op1_addr = OP1_REG_ADDR();
  5268. if (orig_op1_type != IS_UNKNOWN
  5269. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  5270. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5271. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5272. goto jit_failure;
  5273. }
  5274. if (opline->op1_type == IS_CV
  5275. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5276. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  5277. if (ssa_op->op1_def >= 0) {
  5278. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  5279. }
  5280. }
  5281. } else {
  5282. CHECK_OP1_TRACE_TYPE();
  5283. }
  5284. op2_info = OP2_INFO();
  5285. CHECK_OP2_TRACE_TYPE();
  5286. res_info = RES_INFO();
  5287. avoid_refcounting =
  5288. ssa_op->op1_use >= 0 &&
  5289. ssa->var_info[ssa_op->op1_use].avoid_refcounting;
  5290. if (op1_info & MAY_BE_PACKED_GUARD) {
  5291. ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_PACKED_GUARD;
  5292. } else if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
  5293. && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
  5294. && MAY_BE_PACKED(op1_info)
  5295. && MAY_BE_HASH(op1_info)
  5296. && orig_op1_type != IS_UNKNOWN) {
  5297. op1_info |= MAY_BE_PACKED_GUARD;
  5298. if (orig_op1_type & IS_TRACE_PACKED) {
  5299. op1_info &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
  5300. if (op1_type != IS_UNKNOWN) {
  5301. ssa->var_info[ssa_op->op1_use].type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
  5302. }
  5303. } else {
  5304. op1_info &= ~MAY_BE_ARRAY_PACKED;
  5305. if (op1_type != IS_UNKNOWN) {
  5306. ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_ARRAY_PACKED;
  5307. }
  5308. }
  5309. }
  5310. if (!zend_jit_fetch_dim_read(&dasm_state, opline, ssa, ssa_op,
  5311. op1_info, op1_addr, avoid_refcounting,
  5312. op2_info, res_info, RES_REG_ADDR(), val_type)) {
  5313. goto jit_failure;
  5314. }
  5315. if (ssa_op->op1_def >= 0 && op1_type != IS_UNKNOWN) {
  5316. ssa->var_info[ssa_op->op1_def].type = ssa->var_info[ssa_op->op1_use].type;
  5317. }
  5318. goto done;
  5319. case ZEND_FETCH_DIM_W:
  5320. case ZEND_FETCH_DIM_RW:
  5321. // case ZEND_FETCH_DIM_UNSET:
  5322. case ZEND_FETCH_LIST_W:
  5323. if (opline->op1_type != IS_CV
  5324. && (orig_op1_type == IS_UNKNOWN
  5325. || !(orig_op1_type & IS_TRACE_INDIRECT))) {
  5326. break;
  5327. }
  5328. op1_info = OP1_INFO();
  5329. op1_addr = OP1_REG_ADDR();
  5330. if (opline->op1_type == IS_VAR) {
  5331. if (orig_op1_type != IS_UNKNOWN
  5332. && (orig_op1_type & IS_TRACE_INDIRECT)) {
  5333. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  5334. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  5335. goto jit_failure;
  5336. }
  5337. } else {
  5338. break;
  5339. }
  5340. }
  5341. if (orig_op1_type != IS_UNKNOWN
  5342. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  5343. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5344. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5345. goto jit_failure;
  5346. }
  5347. if (opline->op1_type == IS_CV
  5348. && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  5349. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  5350. }
  5351. } else {
  5352. CHECK_OP1_TRACE_TYPE();
  5353. }
  5354. op2_info = OP2_INFO();
  5355. CHECK_OP2_TRACE_TYPE();
  5356. op1_def_info = OP1_DEF_INFO();
  5357. if (!zend_jit_fetch_dim(&dasm_state, opline,
  5358. op1_info, op1_addr, op2_info, RES_REG_ADDR(), val_type)) {
  5359. goto jit_failure;
  5360. }
  5361. if (ssa_op->result_def > 0
  5362. && (opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_LIST_W)
  5363. && !(op1_info & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
  5364. && !(op2_info & (MAY_BE_UNDEF|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_OBJECT))) {
  5365. ssa->var_info[ssa_op->result_def].indirect_reference = 1;
  5366. }
  5367. goto done;
  5368. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  5369. if ((opline->extended_value & ZEND_ISEMPTY)) {
  5370. // TODO: support for empty() ???
  5371. break;
  5372. }
  5373. op1_info = OP1_INFO();
  5374. op1_addr = OP1_REG_ADDR();
  5375. if (orig_op1_type != IS_UNKNOWN
  5376. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  5377. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5378. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5379. goto jit_failure;
  5380. }
  5381. if (opline->op1_type == IS_CV
  5382. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5383. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  5384. }
  5385. } else {
  5386. CHECK_OP1_TRACE_TYPE();
  5387. }
  5388. op2_info = OP2_INFO();
  5389. CHECK_OP2_TRACE_TYPE();
  5390. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  5391. bool exit_if_true = 0;
  5392. const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
  5393. uint32_t exit_point;
  5394. if (ra) {
  5395. zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra);
  5396. }
  5397. if (ssa_op->op1_use >= 0
  5398. && ssa->var_info[ssa_op->op1_use].avoid_refcounting) {
  5399. /* Temporary reset ZREG_ZVAL_TRY_ADDREF */
  5400. zend_jit_trace_stack *stack = JIT_G(current_frame)->stack;
  5401. uint32_t old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var));
  5402. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE);
  5403. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5404. SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var), old_info);
  5405. } else {
  5406. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5407. }
  5408. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5409. if (!exit_addr) {
  5410. goto jit_failure;
  5411. }
  5412. smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
  5413. } else {
  5414. smart_branch_opcode = 0;
  5415. exit_addr = NULL;
  5416. }
  5417. avoid_refcounting =
  5418. ssa_op->op1_use >= 0 &&
  5419. ssa->var_info[ssa_op->op1_use].avoid_refcounting;
  5420. if (op1_info & MAY_BE_PACKED_GUARD) {
  5421. ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_PACKED_GUARD;
  5422. } else if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
  5423. && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
  5424. && MAY_BE_PACKED(op1_info)
  5425. && MAY_BE_HASH(op1_info)
  5426. && orig_op1_type != IS_UNKNOWN) {
  5427. op1_info |= MAY_BE_PACKED_GUARD;
  5428. if (orig_op1_type & IS_TRACE_PACKED) {
  5429. op1_info &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
  5430. } else {
  5431. op1_info &= ~MAY_BE_ARRAY_PACKED;
  5432. }
  5433. }
  5434. if (!zend_jit_isset_isempty_dim(&dasm_state, opline,
  5435. op1_info, op1_addr, avoid_refcounting,
  5436. op2_info, val_type,
  5437. zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info),
  5438. smart_branch_opcode, -1, -1,
  5439. exit_addr)) {
  5440. goto jit_failure;
  5441. }
  5442. goto done;
  5443. case ZEND_FETCH_OBJ_FUNC_ARG:
  5444. if (!JIT_G(current_frame)
  5445. || !JIT_G(current_frame)->call
  5446. || !JIT_G(current_frame)->call->func
  5447. || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
  5448. break;
  5449. }
  5450. ZEND_FALLTHROUGH;
  5451. case ZEND_FETCH_OBJ_R:
  5452. case ZEND_FETCH_OBJ_IS:
  5453. case ZEND_FETCH_OBJ_W:
  5454. on_this = delayed_fetch_this = 0;
  5455. avoid_refcounting = 0;
  5456. if (opline->op2_type != IS_CONST
  5457. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  5458. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  5459. break;
  5460. }
  5461. ce = NULL;
  5462. ce_is_instanceof = 0;
  5463. op1_indirect = 0;
  5464. if (opline->op1_type == IS_UNUSED) {
  5465. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  5466. ce = op_array->scope;
  5467. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  5468. op1_addr = 0;
  5469. on_this = 1;
  5470. } else {
  5471. op1_info = OP1_INFO();
  5472. if (!(op1_info & MAY_BE_OBJECT)) {
  5473. break;
  5474. }
  5475. op1_addr = OP1_REG_ADDR();
  5476. if (opline->op1_type == IS_VAR
  5477. && opline->opcode == ZEND_FETCH_OBJ_W) {
  5478. if (orig_op1_type != IS_UNKNOWN
  5479. && (orig_op1_type & IS_TRACE_INDIRECT)) {
  5480. op1_indirect = 1;
  5481. if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
  5482. &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
  5483. goto jit_failure;
  5484. }
  5485. }
  5486. }
  5487. if (orig_op1_type != IS_UNKNOWN
  5488. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  5489. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5490. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5491. goto jit_failure;
  5492. }
  5493. if (opline->op1_type == IS_CV
  5494. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5495. ssa->var_info[ssa_op->op1_def >= 0 ? ssa_op->op1_def : ssa_op->op1_use].guarded_reference = 1;
  5496. }
  5497. } else {
  5498. CHECK_OP1_TRACE_TYPE();
  5499. }
  5500. if (!(op1_info & MAY_BE_OBJECT)) {
  5501. break;
  5502. }
  5503. if (ssa->var_info && ssa->ops) {
  5504. if (ssa_op->op1_use >= 0) {
  5505. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  5506. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  5507. ce = op1_ssa->ce;
  5508. ce_is_instanceof = op1_ssa->is_instanceof;
  5509. }
  5510. }
  5511. }
  5512. if (ssa_op->op1_use >= 0) {
  5513. delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
  5514. avoid_refcounting = ssa->var_info[ssa_op->op1_use].avoid_refcounting;
  5515. }
  5516. if (delayed_fetch_this) {
  5517. on_this = 1;
  5518. } else if (ssa_op->op1_use >= 0 && ssa->vars[ssa_op->op1_use].definition >= 0) {
  5519. on_this = ssa_opcodes[ssa->vars[ssa_op->op1_use].definition]->opcode == ZEND_FETCH_THIS;
  5520. } else if (op_array_ssa->ops
  5521. && op_array_ssa->vars
  5522. && op_array_ssa->ops[opline-op_array->opcodes].op1_use >= 0
  5523. && op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition >= 0) {
  5524. on_this = op_array->opcodes[op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition].opcode == ZEND_FETCH_THIS;
  5525. }
  5526. }
  5527. if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op,
  5528. op1_info, op1_addr, op1_indirect, ce, ce_is_instanceof,
  5529. on_this, delayed_fetch_this, avoid_refcounting, op1_ce, val_type,
  5530. zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, MAY_BE_STRING))) {
  5531. goto jit_failure;
  5532. }
  5533. goto done;
  5534. case ZEND_BIND_GLOBAL:
  5535. orig_opline = opline;
  5536. orig_ssa_op = ssa_op;
  5537. while (1) {
  5538. if (!ssa->ops || !ssa->var_info) {
  5539. op1_info = MAY_BE_ANY|MAY_BE_REF;
  5540. } else {
  5541. op1_info = OP1_INFO();
  5542. }
  5543. if (ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
  5544. ssa->var_info[ssa_op->op1_def].guarded_reference = 1;
  5545. }
  5546. if (!zend_jit_bind_global(&dasm_state, opline, op1_info)) {
  5547. goto jit_failure;
  5548. }
  5549. if ((opline+1)->opcode == ZEND_BIND_GLOBAL) {
  5550. opline++;
  5551. ssa_op++;
  5552. } else {
  5553. break;
  5554. }
  5555. }
  5556. opline = orig_opline;
  5557. ssa_op = orig_ssa_op;
  5558. goto done;
  5559. case ZEND_RECV:
  5560. if (!zend_jit_recv(&dasm_state, opline, op_array)) {
  5561. goto jit_failure;
  5562. }
  5563. goto done;
  5564. case ZEND_RECV_INIT:
  5565. orig_opline = opline;
  5566. orig_ssa_op = ssa_op;
  5567. while (1) {
  5568. if (!zend_jit_recv_init(&dasm_state, opline, op_array,
  5569. (opline + 1)->opcode != ZEND_RECV_INIT,
  5570. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  5571. goto jit_failure;
  5572. }
  5573. if ((opline+1)->opcode == ZEND_RECV_INIT) {
  5574. opline++;
  5575. ssa_op++;
  5576. } else {
  5577. break;
  5578. }
  5579. }
  5580. opline = orig_opline;
  5581. ssa_op = orig_ssa_op;
  5582. goto done;
  5583. case ZEND_FREE:
  5584. case ZEND_FE_FREE:
  5585. op1_info = OP1_INFO();
  5586. if (!zend_jit_free(&dasm_state, opline, op1_info,
  5587. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  5588. goto jit_failure;
  5589. }
  5590. goto done;
  5591. case ZEND_ECHO:
  5592. op1_info = OP1_INFO();
  5593. CHECK_OP1_TRACE_TYPE();
  5594. if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
  5595. break;
  5596. }
  5597. if (!zend_jit_echo(&dasm_state, opline, op1_info)) {
  5598. goto jit_failure;
  5599. }
  5600. goto done;
  5601. case ZEND_STRLEN:
  5602. op1_info = OP1_INFO();
  5603. op1_addr = OP1_REG_ADDR();
  5604. if (orig_op1_type == (IS_TRACE_REFERENCE|IS_STRING)) {
  5605. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5606. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5607. goto jit_failure;
  5608. }
  5609. if (opline->op1_type == IS_CV
  5610. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5611. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  5612. }
  5613. } else {
  5614. CHECK_OP1_TRACE_TYPE();
  5615. if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
  5616. break;
  5617. }
  5618. }
  5619. if (!zend_jit_strlen(&dasm_state, opline, op1_info, op1_addr, RES_REG_ADDR())) {
  5620. goto jit_failure;
  5621. }
  5622. goto done;
  5623. case ZEND_COUNT:
  5624. op1_info = OP1_INFO();
  5625. op1_addr = OP1_REG_ADDR();
  5626. if (orig_op1_type == (IS_TRACE_REFERENCE|IS_ARRAY)) {
  5627. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5628. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5629. goto jit_failure;
  5630. }
  5631. if (opline->op1_type == IS_CV
  5632. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5633. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  5634. }
  5635. } else {
  5636. CHECK_OP1_TRACE_TYPE();
  5637. if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_ARRAY) {
  5638. break;
  5639. }
  5640. }
  5641. if (!zend_jit_count(&dasm_state, opline, op1_info, op1_addr, RES_REG_ADDR(), zend_may_throw(opline, ssa_op, op_array, ssa))) {
  5642. goto jit_failure;
  5643. }
  5644. goto done;
  5645. case ZEND_FETCH_THIS:
  5646. delayed_fetch_this = 0;
  5647. if (ssa_op->result_def >= 0 && opline->result_type != IS_CV) {
  5648. if (zend_jit_may_delay_fetch_this(op_array, ssa, ssa_opcodes, ssa_op)) {
  5649. ssa->var_info[ssa_op->result_def].delayed_fetch_this = 1;
  5650. delayed_fetch_this = 1;
  5651. }
  5652. }
  5653. if (!zend_jit_fetch_this(&dasm_state, opline, op_array, delayed_fetch_this)) {
  5654. goto jit_failure;
  5655. }
  5656. goto done;
  5657. case ZEND_SWITCH_LONG:
  5658. case ZEND_SWITCH_STRING:
  5659. case ZEND_MATCH:
  5660. if (!zend_jit_switch(&dasm_state, opline, op_array, op_array_ssa, p+1, &zend_jit_traces[ZEND_JIT_TRACE_NUM])) {
  5661. goto jit_failure;
  5662. }
  5663. goto done;
  5664. case ZEND_VERIFY_RETURN_TYPE:
  5665. if (opline->op1_type == IS_UNUSED) {
  5666. /* Always throws */
  5667. break;
  5668. }
  5669. if (opline->op1_type == IS_CONST) {
  5670. /* TODO Different instruction format, has return value */
  5671. break;
  5672. }
  5673. if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
  5674. /* Not worth bothering with */
  5675. break;
  5676. }
  5677. op1_info = OP1_INFO();
  5678. CHECK_OP1_TRACE_TYPE();
  5679. if (op1_info & MAY_BE_REF) {
  5680. /* TODO May need reference unwrapping. */
  5681. break;
  5682. }
  5683. if (!zend_jit_verify_return_type(&dasm_state, opline, op_array, op1_info)) {
  5684. goto jit_failure;
  5685. }
  5686. goto done;
  5687. case ZEND_FE_RESET_R:
  5688. op1_info = OP1_INFO();
  5689. CHECK_OP1_TRACE_TYPE();
  5690. if ((op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) != MAY_BE_ARRAY) {
  5691. break;
  5692. }
  5693. if (!zend_jit_fe_reset(&dasm_state, opline, op1_info)) {
  5694. goto jit_failure;
  5695. }
  5696. goto done;
  5697. case ZEND_FE_FETCH_R:
  5698. op1_info = OP1_INFO();
  5699. CHECK_OP1_TRACE_TYPE();
  5700. if ((op1_info & MAY_BE_ANY) != MAY_BE_ARRAY) {
  5701. break;
  5702. }
  5703. if ((p+1)->op == ZEND_JIT_TRACE_VM || (p+1)->op == ZEND_JIT_TRACE_END) {
  5704. const zend_op *exit_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
  5705. uint32_t exit_point;
  5706. if ((p+1)->opline == exit_opline) {
  5707. /* taken branch (exit from loop) */
  5708. exit_opline = opline;
  5709. smart_branch_opcode = ZEND_NOP;
  5710. } else if ((p+1)->opline == opline + 1) {
  5711. /* not taken branch (loop) */
  5712. smart_branch_opcode = ZEND_JMP;
  5713. } else {
  5714. ZEND_UNREACHABLE();
  5715. }
  5716. exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
  5717. exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  5718. if (!exit_addr) {
  5719. goto jit_failure;
  5720. }
  5721. } else {
  5722. ZEND_UNREACHABLE();
  5723. }
  5724. if (!zend_jit_fe_fetch(&dasm_state, opline, op1_info, OP2_INFO(),
  5725. -1, smart_branch_opcode, exit_addr)) {
  5726. goto jit_failure;
  5727. }
  5728. goto done;
  5729. case ZEND_FETCH_CONSTANT:
  5730. if (!zend_jit_fetch_constant(&dasm_state, opline, op_array, ssa, ssa_op, RES_REG_ADDR())) {
  5731. goto jit_failure;
  5732. }
  5733. goto done;
  5734. case ZEND_INIT_METHOD_CALL:
  5735. if (opline->op2_type != IS_CONST
  5736. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING) {
  5737. goto generic_dynamic_call;
  5738. }
  5739. on_this = delayed_fetch_this = 0;
  5740. ce = NULL;
  5741. ce_is_instanceof = 0;
  5742. if (opline->op1_type == IS_UNUSED) {
  5743. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  5744. ce = op_array->scope;
  5745. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  5746. op1_addr = 0;
  5747. on_this = 1;
  5748. } else {
  5749. op1_info = OP1_INFO();
  5750. op1_addr = OP1_REG_ADDR();
  5751. if (polymorphic_side_trace) {
  5752. op1_info = MAY_BE_OBJECT;
  5753. op1_addr = 0;
  5754. } else if (orig_op1_type != IS_UNKNOWN
  5755. && (orig_op1_type & IS_TRACE_REFERENCE)) {
  5756. if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
  5757. !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
  5758. goto jit_failure;
  5759. }
  5760. if (opline->op1_type == IS_CV
  5761. && ssa->vars[ssa_op->op1_use].alias == NO_ALIAS) {
  5762. ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
  5763. }
  5764. } else {
  5765. CHECK_OP1_TRACE_TYPE();
  5766. }
  5767. if (ssa->var_info && ssa->ops) {
  5768. if (ssa_op->op1_use >= 0) {
  5769. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  5770. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  5771. ce = op1_ssa->ce;
  5772. ce_is_instanceof = op1_ssa->is_instanceof;
  5773. }
  5774. }
  5775. }
  5776. if (ssa_op->op1_use >= 0) {
  5777. delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
  5778. }
  5779. if (delayed_fetch_this) {
  5780. on_this = 1;
  5781. } else if (ssa_op->op1_use >= 0 && ssa->vars[ssa_op->op1_use].definition >= 0) {
  5782. on_this = ssa_opcodes[ssa->vars[ssa_op->op1_use].definition]->opcode == ZEND_FETCH_THIS;
  5783. } else if (op_array_ssa->ops
  5784. && op_array_ssa->vars
  5785. && op_array_ssa->ops[opline-op_array->opcodes].op1_use >= 0
  5786. && op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition >= 0) {
  5787. on_this = op_array->opcodes[op_array_ssa->vars[op_array_ssa->ops[opline-op_array->opcodes].op1_use].definition].opcode == ZEND_FETCH_THIS;
  5788. }
  5789. }
  5790. frame_flags = TRACE_FRAME_MASK_NESTED;
  5791. if (!zend_jit_init_method_call(&dasm_state, opline,
  5792. op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1,
  5793. op_array, ssa, ssa_op, frame->call_level,
  5794. op1_info, op1_addr, ce, ce_is_instanceof, on_this, delayed_fetch_this, op1_ce,
  5795. p + 1, peek_checked_stack - checked_stack, polymorphic_side_trace)) {
  5796. goto jit_failure;
  5797. }
  5798. goto done;
  5799. case ZEND_INIT_DYNAMIC_CALL:
  5800. if (orig_op2_type != IS_OBJECT || op2_ce != zend_ce_closure) {
  5801. goto generic_dynamic_call;
  5802. }
  5803. op2_info = OP2_INFO();
  5804. CHECK_OP2_TRACE_TYPE();
  5805. frame_flags = TRACE_FRAME_MASK_NESTED;
  5806. if (!zend_jit_init_closure_call(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, peek_checked_stack - checked_stack)) {
  5807. goto jit_failure;
  5808. }
  5809. goto done;
  5810. case ZEND_INIT_STATIC_METHOD_CALL:
  5811. generic_dynamic_call:
  5812. if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) {
  5813. goto jit_failure;
  5814. }
  5815. if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func
  5816. && (opline->opcode != ZEND_INIT_STATIC_METHOD_CALL
  5817. || opline->op1_type != IS_CONST
  5818. || opline->op2_type != IS_CONST
  5819. || zend_jit_may_be_modified((p+1)->func, op_array))) {
  5820. if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
  5821. goto jit_failure;
  5822. }
  5823. }
  5824. goto done;
  5825. case ZEND_INIT_USER_CALL:
  5826. if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) {
  5827. goto jit_failure;
  5828. }
  5829. if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func
  5830. && (opline->op2_type != IS_CONST
  5831. || zend_jit_may_be_modified((p+1)->func, op_array))) {
  5832. if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
  5833. goto jit_failure;
  5834. }
  5835. }
  5836. goto done;
  5837. case ZEND_NEW:
  5838. if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) {
  5839. goto jit_failure;
  5840. }
  5841. if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func
  5842. && (opline->op1_type != IS_CONST
  5843. || zend_jit_may_be_modified((p+1)->func, op_array))) {
  5844. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_OBJECT, 1);
  5845. if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
  5846. goto jit_failure;
  5847. }
  5848. }
  5849. goto done;
  5850. case ZEND_SEND_ARRAY:
  5851. case ZEND_SEND_UNPACK:
  5852. if (JIT_G(current_frame)
  5853. && JIT_G(current_frame)->call) {
  5854. TRACE_FRAME_SET_UNKNOWN_NUM_ARGS(JIT_G(current_frame)->call);
  5855. }
  5856. break;
  5857. case ZEND_ROPE_INIT:
  5858. case ZEND_ROPE_ADD:
  5859. case ZEND_ROPE_END:
  5860. op2_info = OP2_INFO();
  5861. CHECK_OP2_TRACE_TYPE();
  5862. if ((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
  5863. break;
  5864. }
  5865. if (!zend_jit_rope(&dasm_state, opline, op2_info)) {
  5866. goto jit_failure;
  5867. }
  5868. goto done;
  5869. default:
  5870. break;
  5871. }
  5872. }
  5873. if (opline->opcode != ZEND_NOP && opline->opcode != ZEND_JMP) {
  5874. gen_handler = 1;
  5875. op1_info = OP1_INFO();
  5876. op2_info = OP2_INFO();
  5877. if (op1_info & MAY_BE_GUARD) {
  5878. op1_info = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  5879. }
  5880. if (op2_info & MAY_BE_GUARD) {
  5881. op2_info = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  5882. }
  5883. if (!zend_jit_trace_handler(&dasm_state, op_array, opline,
  5884. zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info), p + 1)) {
  5885. goto jit_failure;
  5886. }
  5887. }
  5888. done:
  5889. polymorphic_side_trace = 0;
  5890. switch (opline->opcode) {
  5891. case ZEND_DO_FCALL:
  5892. case ZEND_DO_ICALL:
  5893. case ZEND_DO_UCALL:
  5894. case ZEND_DO_FCALL_BY_NAME:
  5895. frame->call_level--;
  5896. }
  5897. if (ra) {
  5898. zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra);
  5899. }
  5900. if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))
  5901. && STACK_REG(stack, EX_VAR_TO_NUM(opline->op1.var)) > ZREG_NUM) {
  5902. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE);
  5903. }
  5904. if (opline->opcode == ZEND_ROPE_INIT) {
  5905. /* clear stack slots used by rope */
  5906. uint32_t var = EX_VAR_TO_NUM(opline->result.var);
  5907. uint32_t count =
  5908. ((opline->extended_value * sizeof(void*)) + (sizeof(zval)-1)) / sizeof(zval);
  5909. do {
  5910. SET_STACK_TYPE(stack, var, IS_UNKNOWN, 1);
  5911. var++;
  5912. count--;
  5913. } while (count);
  5914. }
  5915. if (ssa_op) {
  5916. zend_ssa_range tmp;
  5917. /* Keep information about known types on abstract stack */
  5918. if (ssa_op->result_def >= 0) {
  5919. zend_uchar type = IS_UNKNOWN;
  5920. if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0
  5921. || send_result) {
  5922. /* we didn't set result variable */
  5923. type = IS_UNKNOWN;
  5924. } else if (!(ssa->var_info[ssa_op->result_def].type & MAY_BE_GUARD)
  5925. && has_concrete_type(ssa->var_info[ssa_op->result_def].type)) {
  5926. type = concrete_type(ssa->var_info[ssa_op->result_def].type);
  5927. } else if (opline->opcode == ZEND_QM_ASSIGN) {
  5928. if (opline->op1_type != IS_CONST) {
  5929. /* copy */
  5930. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var));
  5931. }
  5932. } else if (opline->opcode == ZEND_ASSIGN) {
  5933. if (opline->op2_type != IS_CONST
  5934. && ssa_op->op1_use >= 0
  5935. /* assignment to typed reference may cause conversion */
  5936. && (ssa->var_info[ssa_op->op1_use].type & MAY_BE_REF) == 0) {
  5937. /* copy */
  5938. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var));
  5939. }
  5940. } else if (opline->opcode == ZEND_POST_INC
  5941. || opline->opcode == ZEND_POST_DEC) {
  5942. /* copy */
  5943. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var));
  5944. }
  5945. if (opline->opcode == ZEND_JMP_SET
  5946. || opline->opcode == ZEND_COALESCE
  5947. || opline->opcode == ZEND_JMP_NULL) {
  5948. if ((p+1)->op != ZEND_JIT_TRACE_VM) {
  5949. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_UNKNOWN, 1);
  5950. } else if ((p+1)->opline != (opline + 1)) {
  5951. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), type, 1);
  5952. }
  5953. } else {
  5954. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), type,
  5955. (gen_handler || type == IS_UNKNOWN || !ra || !ra[ssa_op->result_def]));
  5956. if (ssa->var_info[ssa_op->result_def].type & MAY_BE_INDIRECT) {
  5957. RESET_STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var));
  5958. }
  5959. if (type != IS_UNKNOWN) {
  5960. ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
  5961. if (opline->opcode == ZEND_FETCH_THIS
  5962. && delayed_fetch_this) {
  5963. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_THIS);
  5964. } else if (ssa->var_info[ssa_op->result_def].avoid_refcounting) {
  5965. SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_ZVAL_TRY_ADDREF);
  5966. } else if (ra && ra[ssa_op->result_def]) {
  5967. SET_STACK_REG_EX(stack, EX_VAR_TO_NUM(opline->result.var), ra[ssa_op->result_def]->reg,
  5968. ra[ssa_op->result_def]->flags & ZREG_STORE);
  5969. }
  5970. }
  5971. }
  5972. if (type == IS_LONG
  5973. && zend_inference_propagate_range(op_array, ssa, (zend_op*)opline, (zend_ssa_op*)ssa_op, ssa_op->result_def, &tmp)) {
  5974. ssa->var_info[ssa_op->result_def].range.min = tmp.min;
  5975. ssa->var_info[ssa_op->result_def].range.max = tmp.max;
  5976. ssa->var_info[ssa_op->result_def].range.underflow = 0;
  5977. ssa->var_info[ssa_op->result_def].range.overflow = 0;
  5978. ssa->var_info[ssa_op->result_def].has_range = 1;
  5979. }
  5980. }
  5981. if (ssa_op->op1_def >= 0
  5982. && (opline->opcode != ZEND_QM_ASSIGN
  5983. || opline->result_type != IS_CV
  5984. || opline->result.var != opline->op1.var)) {
  5985. zend_uchar type = IS_UNKNOWN;
  5986. if (!(ssa->var_info[ssa_op->op1_def].type & MAY_BE_GUARD)
  5987. && has_concrete_type(ssa->var_info[ssa_op->op1_def].type)) {
  5988. type = concrete_type(ssa->var_info[ssa_op->op1_def].type);
  5989. } else if (opline->opcode == ZEND_ASSIGN) {
  5990. if (!(OP1_INFO() & MAY_BE_REF)
  5991. || STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var)) != IS_UNKNOWN) {
  5992. if (opline->op2_type != IS_CONST) {
  5993. /* copy */
  5994. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var));
  5995. }
  5996. }
  5997. } else if (opline->opcode == ZEND_SEND_VAR
  5998. || opline->opcode == ZEND_CAST
  5999. || opline->opcode == ZEND_QM_ASSIGN
  6000. || opline->opcode == ZEND_JMP_SET
  6001. || opline->opcode == ZEND_COALESCE
  6002. || opline->opcode == ZEND_JMP_NULL
  6003. || opline->opcode == ZEND_FE_RESET_R) {
  6004. /* keep old value */
  6005. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var));
  6006. }
  6007. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), type,
  6008. (gen_handler || type == IS_UNKNOWN || !ra ||
  6009. (!ra[ssa_op->op1_def] &&
  6010. (opline->opcode == ZEND_ASSIGN || !ssa->vars[ssa_op->op1_def].no_val))));
  6011. if (type != IS_UNKNOWN) {
  6012. ssa->var_info[ssa_op->op1_def].type &= ~MAY_BE_GUARD;
  6013. if (ra && ra[ssa_op->op1_def]) {
  6014. uint8_t flags = ra[ssa_op->op1_def]->flags & ZREG_STORE;
  6015. if (ssa_op->op1_use >= 0) {
  6016. if (opline->opcode == ZEND_SEND_VAR
  6017. || opline->opcode == ZEND_CAST
  6018. || opline->opcode == ZEND_QM_ASSIGN
  6019. || opline->opcode == ZEND_JMP_SET
  6020. || opline->opcode == ZEND_COALESCE
  6021. || opline->opcode == ZEND_JMP_NULL
  6022. || opline->opcode == ZEND_FE_RESET_R) {
  6023. if (!ra[ssa_op->op1_use]) {
  6024. flags |= ZREG_LOAD;
  6025. }
  6026. }
  6027. }
  6028. SET_STACK_REG_EX(stack, EX_VAR_TO_NUM(opline->op1.var), ra[ssa_op->op1_def]->reg, flags);
  6029. }
  6030. }
  6031. if (type == IS_LONG
  6032. && zend_inference_propagate_range(op_array, ssa, (zend_op*)opline, (zend_ssa_op*)ssa_op, ssa_op->op1_def, &tmp)) {
  6033. ssa->var_info[ssa_op->op1_def].range.min = tmp.min;
  6034. ssa->var_info[ssa_op->op1_def].range.max = tmp.max;
  6035. ssa->var_info[ssa_op->op1_def].range.underflow = 0;
  6036. ssa->var_info[ssa_op->op1_def].range.overflow = 0;
  6037. ssa->var_info[ssa_op->op1_def].has_range = 1;
  6038. }
  6039. }
  6040. if (ssa_op->op2_def >= 0
  6041. && (opline->opcode != ZEND_ASSIGN
  6042. || opline->op1_type != IS_CV
  6043. || opline->op1.var != opline->op2.var)) {
  6044. zend_uchar type = IS_UNKNOWN;
  6045. if (!(ssa->var_info[ssa_op->op2_def].type & MAY_BE_GUARD)
  6046. && has_concrete_type(ssa->var_info[ssa_op->op2_def].type)) {
  6047. type = concrete_type(ssa->var_info[ssa_op->op2_def].type);
  6048. } else if (opline->opcode == ZEND_ASSIGN) {
  6049. /* keep old value */
  6050. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var));
  6051. }
  6052. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var), type,
  6053. (gen_handler || type == IS_UNKNOWN || !ra ||
  6054. (!ra[ssa_op->op2_def] && !ssa->vars[ssa_op->op2_def].no_val)));
  6055. if (type != IS_UNKNOWN) {
  6056. ssa->var_info[ssa_op->op2_def].type &= ~MAY_BE_GUARD;
  6057. if (ra && ra[ssa_op->op2_def]) {
  6058. uint8_t flags = ra[ssa_op->op2_def]->flags & ZREG_STORE;
  6059. if (ssa_op->op2_use >= 0) {
  6060. if (opline->opcode == ZEND_ASSIGN) {
  6061. if (!ra[ssa_op->op2_use]
  6062. || ra[ssa_op->op2_use]->reg != ra[ssa_op->op2_def]->reg) {
  6063. flags |= ZREG_LOAD;
  6064. }
  6065. }
  6066. }
  6067. SET_STACK_REG_EX(stack, EX_VAR_TO_NUM(opline->op2.var), ra[ssa_op->op2_def]->reg, flags);
  6068. }
  6069. }
  6070. if (type == IS_LONG
  6071. && zend_inference_propagate_range(op_array, ssa, (zend_op*)opline, (zend_ssa_op*)ssa_op, ssa_op->op2_def, &tmp)) {
  6072. ssa->var_info[ssa_op->op2_def].range.min = tmp.min;
  6073. ssa->var_info[ssa_op->op2_def].range.max = tmp.max;
  6074. ssa->var_info[ssa_op->op2_def].range.underflow = 0;
  6075. ssa->var_info[ssa_op->op2_def].range.overflow = 0;
  6076. ssa->var_info[ssa_op->op2_def].has_range = 1;
  6077. }
  6078. }
  6079. switch (opline->opcode) {
  6080. case ZEND_ASSIGN_DIM:
  6081. case ZEND_ASSIGN_OBJ:
  6082. case ZEND_ASSIGN_STATIC_PROP:
  6083. case ZEND_ASSIGN_DIM_OP:
  6084. case ZEND_ASSIGN_OBJ_OP:
  6085. case ZEND_ASSIGN_STATIC_PROP_OP:
  6086. case ZEND_ASSIGN_OBJ_REF:
  6087. case ZEND_ASSIGN_STATIC_PROP_REF:
  6088. /* OP_DATA */
  6089. ssa_op++;
  6090. opline++;
  6091. if (ssa_op->op1_def >= 0) {
  6092. zend_uchar type = IS_UNKNOWN;
  6093. if (!(ssa->var_info[ssa_op->op1_def].type & MAY_BE_GUARD)
  6094. && has_concrete_type(ssa->var_info[ssa_op->op1_def].type)) {
  6095. type = concrete_type(ssa->var_info[ssa_op->op1_def].type);
  6096. } else if ((opline-1)->opcode == ZEND_ASSIGN_DIM
  6097. || (opline-1)->opcode == ZEND_ASSIGN_OBJ
  6098. || (opline-1)->opcode == ZEND_ASSIGN_STATIC_PROP) {
  6099. /* keep old value */
  6100. type = STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var));
  6101. }
  6102. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), type,
  6103. (gen_handler || type == IS_UNKNOWN || !ra || !ra[ssa_op->op1_def]));
  6104. if (type != IS_UNKNOWN) {
  6105. ssa->var_info[ssa_op->op1_def].type &= ~MAY_BE_GUARD;
  6106. if (ra && ra[ssa_op->op1_def]) {
  6107. SET_STACK_REG_EX(stack, EX_VAR_TO_NUM(opline->op1.var), ra[ssa_op->op1_def]->reg,
  6108. ra[ssa_op->op1_def]->flags & ZREG_STORE);
  6109. }
  6110. }
  6111. if (type == IS_LONG
  6112. && zend_inference_propagate_range(op_array, ssa, (zend_op*)opline, (zend_ssa_op*)ssa_op, ssa_op->op1_def, &tmp)) {
  6113. ssa->var_info[ssa_op->op1_def].range.min = tmp.min;
  6114. ssa->var_info[ssa_op->op1_def].range.max = tmp.max;
  6115. ssa->var_info[ssa_op->op1_def].range.underflow = 0;
  6116. ssa->var_info[ssa_op->op1_def].range.overflow = 0;
  6117. ssa->var_info[ssa_op->op1_def].has_range = 1;
  6118. }
  6119. }
  6120. ssa_op++;
  6121. break;
  6122. case ZEND_RECV_INIT:
  6123. ssa_op++;
  6124. opline++;
  6125. while (opline->opcode == ZEND_RECV_INIT) {
  6126. if (ssa_op->result_def >= 0) {
  6127. zend_uchar type = IS_UNKNOWN;
  6128. if (!(ssa->var_info[ssa_op->result_def].type & MAY_BE_GUARD)
  6129. && has_concrete_type(ssa->var_info[ssa_op->result_def].type)) {
  6130. type = concrete_type(ssa->var_info[ssa_op->result_def].type);
  6131. }
  6132. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), type,
  6133. (gen_handler || !ra || !ra[ssa_op->result_def]));
  6134. if (ra && ra[ssa_op->result_def]) {
  6135. SET_STACK_REG_EX(stack, EX_VAR_TO_NUM(opline->result.var), ra[ssa_op->result_def]->reg,
  6136. ra[ssa_op->result_def]->flags & ZREG_STORE);
  6137. }
  6138. }
  6139. ssa_op++;
  6140. opline++;
  6141. }
  6142. break;
  6143. case ZEND_BIND_GLOBAL:
  6144. ssa_op++;
  6145. opline++;
  6146. while (opline->opcode == ZEND_BIND_GLOBAL) {
  6147. if (ssa_op->op1_def >= 0) {
  6148. zend_uchar type = IS_UNKNOWN;
  6149. if (!(ssa->var_info[ssa_op->op1_def].type & MAY_BE_GUARD)
  6150. && has_concrete_type(ssa->var_info[ssa_op->op1_def].type)) {
  6151. type = concrete_type(ssa->var_info[ssa_op->op1_def].type);
  6152. }
  6153. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), type,
  6154. (gen_handler || !ra || !ra[ssa_op->op1_def]));
  6155. if (ra && ra[ssa_op->op1_def]) {
  6156. SET_STACK_REG_EX(stack, EX_VAR_TO_NUM(opline->op1.var), ra[ssa_op->op1_def]->reg,
  6157. ra[ssa_op->op1_def]->flags & ZREG_STORE);
  6158. }
  6159. }
  6160. ssa_op++;
  6161. opline++;
  6162. }
  6163. break;
  6164. default:
  6165. ssa_op += zend_jit_trace_op_len(opline);
  6166. break;
  6167. }
  6168. if (send_result) {
  6169. ssa_op++;
  6170. p++;
  6171. if ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE) {
  6172. p++;
  6173. }
  6174. send_result = 0;
  6175. }
  6176. }
  6177. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  6178. call = frame->call;
  6179. assert(call && &call->func->op_array == p->op_array);
  6180. if (opline->opcode == ZEND_DO_UCALL
  6181. || opline->opcode == ZEND_DO_FCALL_BY_NAME
  6182. || opline->opcode == ZEND_DO_FCALL) {
  6183. frame->call_opline = opline;
  6184. /* Check if SEND_UNPACK/SEND_ARRAY may cause enter at different opline */
  6185. if (opline > op_array->opcodes) {
  6186. const zend_op *prev_opline = opline - 1;
  6187. while (prev_opline->opcode == ZEND_EXT_FCALL_BEGIN || prev_opline->opcode == ZEND_TICKS) {
  6188. prev_opline--;
  6189. }
  6190. JIT_G(current_frame) = call;
  6191. if ((prev_opline->opcode == ZEND_SEND_ARRAY
  6192. || prev_opline->opcode == ZEND_SEND_UNPACK
  6193. || prev_opline->opcode == ZEND_CHECK_UNDEF_ARGS)
  6194. && p->op_array->num_args
  6195. && (p->op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0
  6196. && ((p+1)->op == ZEND_JIT_TRACE_VM
  6197. || (p+1)->op == ZEND_JIT_TRACE_END)
  6198. && (TRACE_FRAME_NUM_ARGS(call) < 0
  6199. || TRACE_FRAME_NUM_ARGS(call) < p->op_array->num_args)
  6200. && !zend_jit_trace_opline_guard(&dasm_state, (p+1)->opline)) {
  6201. goto jit_failure;
  6202. }
  6203. JIT_G(current_frame) = frame;
  6204. }
  6205. }
  6206. if ((p+1)->op == ZEND_JIT_TRACE_END) {
  6207. p++;
  6208. break;
  6209. }
  6210. if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
  6211. if (TRACE_FRAME_IS_THIS_CHECKED(frame)) {
  6212. TRACE_FRAME_SET_THIS_CHECKED(call);
  6213. }
  6214. } else if (op_array->scope && !(op_array->fn_flags & ZEND_ACC_STATIC)) {
  6215. TRACE_FRAME_SET_THIS_CHECKED(call);
  6216. }
  6217. op_array = (zend_op_array*)p->op_array;
  6218. jit_extension =
  6219. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6220. op_array_ssa = &jit_extension->func_info.ssa;
  6221. frame->call = call->prev;
  6222. call->prev = frame;
  6223. if (p->info & ZEND_JIT_TRACE_RETURN_VALUE_USED) {
  6224. TRACE_FRAME_SET_RETURN_VALUE_USED(call);
  6225. } else {
  6226. TRACE_FRAME_SET_RETURN_VALUE_UNUSED(call);
  6227. }
  6228. JIT_G(current_frame) = frame = call;
  6229. stack = frame->stack;
  6230. if (ra) {
  6231. int j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  6232. for (i = 0; i < op_array->last_var; i++,j++) {
  6233. if (ra[j] && (ra[j]->flags & ZREG_LOAD) != 0) {
  6234. SET_STACK_REG_EX(stack, i, ra[j]->reg, ZREG_LOAD);
  6235. if (!zend_jit_load_var(&dasm_state, ssa->var_info[j].type, i, ra[j]->reg)) {
  6236. goto jit_failure;
  6237. }
  6238. }
  6239. }
  6240. }
  6241. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  6242. op_array = (zend_op_array*)p->op_array;
  6243. jit_extension =
  6244. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6245. op_array_ssa = &jit_extension->func_info.ssa;
  6246. top = frame;
  6247. if (frame->prev) {
  6248. checked_stack -= frame->used_stack;
  6249. frame = frame->prev;
  6250. stack = frame->stack;
  6251. ZEND_ASSERT(&frame->func->op_array == op_array);
  6252. } else {
  6253. frame = zend_jit_trace_ret_frame(frame, op_array);
  6254. TRACE_FRAME_INIT(frame, op_array, TRACE_FRAME_MASK_UNKNOWN_RETURN, -1);
  6255. frame->used_stack = checked_stack = peek_checked_stack = 0;
  6256. stack = frame->stack;
  6257. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
  6258. uint32_t j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  6259. for (i = 0; i < op_array->last_var + op_array->T; i++, j++) {
  6260. /* Initialize abstract stack using SSA */
  6261. if (!(ssa->var_info[j].type & MAY_BE_GUARD)
  6262. && has_concrete_type(ssa->var_info[j].type)) {
  6263. SET_STACK_TYPE(stack, i, concrete_type(ssa->var_info[j].type), 1);
  6264. } else {
  6265. SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
  6266. }
  6267. }
  6268. if (ra) {
  6269. j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  6270. for (i = 0; i < op_array->last_var + op_array->T; i++, j++) {
  6271. if (ra[j] && (ra[j]->flags & ZREG_LOAD) != 0) {
  6272. SET_STACK_REG_EX(stack, i, ra[j]->reg, ZREG_LOAD);
  6273. if (!zend_jit_load_var(&dasm_state, ssa->var_info[j].type, i, ra[j]->reg)) {
  6274. goto jit_failure;
  6275. }
  6276. }
  6277. }
  6278. }
  6279. } else {
  6280. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  6281. SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
  6282. }
  6283. }
  6284. opline = NULL;
  6285. }
  6286. JIT_G(current_frame) = frame;
  6287. if (res_type != IS_UNKNOWN
  6288. && (p+1)->op == ZEND_JIT_TRACE_VM) {
  6289. const zend_op *opline = (p+1)->opline - 1;
  6290. if (opline->result_type != IS_UNUSED) {
  6291. SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), res_type, 1);
  6292. }
  6293. }
  6294. res_type = IS_UNKNOWN;
  6295. } else if (p->op == ZEND_JIT_TRACE_END) {
  6296. break;
  6297. } else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
  6298. const zend_op *init_opline = zend_jit_trace_find_init_fcall_op(p, op_array);
  6299. int num_args = -1;
  6300. if (init_opline
  6301. && init_opline->extended_value <= TRACE_FRAME_MAX_NUM_ARGS) {
  6302. num_args = init_opline->extended_value;
  6303. }
  6304. call = top;
  6305. TRACE_FRAME_INIT(call, p->func, frame_flags, num_args);
  6306. call->prev = frame->call;
  6307. if (!(p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL)) {
  6308. TRACE_FRAME_SET_LAST_SEND_BY_VAL(call);
  6309. }
  6310. if (init_opline
  6311. && init_opline->opcode != ZEND_NEW
  6312. && (init_opline->opcode != ZEND_INIT_METHOD_CALL
  6313. || init_opline->op1_type == IS_UNDEF)
  6314. && (init_opline->opcode != ZEND_INIT_USER_CALL
  6315. || (p->func && (!p->func->common.scope || (p->func->common.fn_flags & ZEND_ACC_STATIC))))
  6316. && (init_opline->opcode != ZEND_INIT_DYNAMIC_CALL
  6317. || (p->func && (!p->func->common.scope || (p->func->common.fn_flags & ZEND_ACC_STATIC))))
  6318. ) {
  6319. TRACE_FRAME_SET_NO_NEED_RELEASE_THIS(call);
  6320. }
  6321. frame->call = call;
  6322. top = zend_jit_trace_call_frame(top, p->op_array);
  6323. if (p->func) {
  6324. if (p->func->type == ZEND_USER_FUNCTION) {
  6325. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
  6326. zend_jit_op_array_trace_extension *jit_extension =
  6327. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(p->op_array);
  6328. i = 0;
  6329. while (i < p->op_array->num_args) {
  6330. /* Types of arguments are going to be stored in abstract stack when processing SEV instruction */
  6331. SET_STACK_TYPE(call->stack, i, IS_UNKNOWN, 1);
  6332. i++;
  6333. }
  6334. while (i < p->op_array->last_var) {
  6335. if (jit_extension
  6336. && zend_jit_var_may_alias(p->op_array, &jit_extension->func_info.ssa, i) != NO_ALIAS) {
  6337. SET_STACK_TYPE(call->stack, i, IS_UNKNOWN, 1);
  6338. } else {
  6339. SET_STACK_TYPE(call->stack, i, IS_UNDEF, 1);
  6340. }
  6341. i++;
  6342. }
  6343. while (i < p->op_array->last_var + p->op_array->T) {
  6344. SET_STACK_TYPE(call->stack, i, IS_UNKNOWN, 1);
  6345. i++;
  6346. }
  6347. } else {
  6348. for (i = 0; i < p->op_array->last_var + p->op_array->T; i++) {
  6349. SET_STACK_TYPE(call->stack, i, IS_UNKNOWN, 1);
  6350. }
  6351. }
  6352. } else {
  6353. ZEND_ASSERT(p->func->type == ZEND_INTERNAL_FUNCTION);
  6354. for (i = 0; i < p->op_array->num_args; i++) {
  6355. SET_STACK_TYPE(call->stack, i, IS_UNKNOWN, 1);
  6356. }
  6357. }
  6358. if (p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL) {
  6359. int skip_guard = 0;
  6360. if (init_opline) {
  6361. zend_call_info *call_info = jit_extension->func_info.callee_info;
  6362. while (call_info) {
  6363. if (call_info->caller_init_opline == init_opline
  6364. && !call_info->is_prototype) {
  6365. if (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE) {
  6366. if (init_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL
  6367. && init_opline->op1_type != IS_CONST) {
  6368. break;
  6369. } else if (init_opline->opcode == ZEND_INIT_METHOD_CALL) {
  6370. break;
  6371. }
  6372. }
  6373. skip_guard = 1;
  6374. break;
  6375. }
  6376. call_info = call_info->next_callee;
  6377. }
  6378. if (!skip_guard
  6379. && !zend_jit_may_be_polymorphic_call(init_opline)
  6380. && !zend_jit_may_be_modified(p->func, op_array)) {
  6381. skip_guard = 1;
  6382. }
  6383. }
  6384. if (!skip_guard) {
  6385. if (!opline) {
  6386. zend_jit_trace_rec *q = p + 1;
  6387. while (q->op != ZEND_JIT_TRACE_VM && q->op != ZEND_JIT_TRACE_END) {
  6388. q++;
  6389. }
  6390. opline = q->opline;
  6391. ZEND_ASSERT(opline != NULL);
  6392. }
  6393. if (!zend_jit_init_fcall_guard(&dasm_state,
  6394. ZEND_JIT_TRACE_FAKE_LEVEL(p->info), p->func, opline)) {
  6395. goto jit_failure;
  6396. }
  6397. }
  6398. }
  6399. }
  6400. if (p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL) {
  6401. frame->call_level++;
  6402. call->used_stack = 0;
  6403. } else {
  6404. if (p->func) {
  6405. call->used_stack = zend_vm_calc_used_stack(init_opline->extended_value, (zend_function*)p->func);
  6406. } else {
  6407. call->used_stack = (ZEND_CALL_FRAME_SLOT + init_opline->extended_value) * sizeof(zval);
  6408. }
  6409. checked_stack += call->used_stack;
  6410. if (checked_stack > peek_checked_stack) {
  6411. peek_checked_stack = checked_stack;
  6412. }
  6413. }
  6414. } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
  6415. call = frame->call;
  6416. if (call) {
  6417. checked_stack -= call->used_stack;
  6418. top = call;
  6419. frame->call = call->prev;
  6420. }
  6421. } else {
  6422. ZEND_UNREACHABLE();
  6423. }
  6424. }
  6425. ZEND_ASSERT(p->op == ZEND_JIT_TRACE_END);
  6426. t = &zend_jit_traces[ZEND_JIT_TRACE_NUM];
  6427. if (!parent_trace && zend_jit_trace_uses_initial_ip()) {
  6428. t->flags |= ZEND_JIT_TRACE_USES_INITIAL_IP;
  6429. }
  6430. if (p->stop == ZEND_JIT_TRACE_STOP_LOOP
  6431. || p->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  6432. || p->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  6433. if (ra) {
  6434. zend_ssa_phi *phi = ssa->blocks[1].phis;
  6435. while (phi) {
  6436. if (ra[phi->ssa_var]
  6437. && ra[phi->sources[1]]
  6438. && STACK_MEM_TYPE(stack, phi->var) != STACK_TYPE(stack, phi->var)
  6439. && (ra[phi->ssa_var]->flags & (ZREG_LOAD|ZREG_STORE)) == 0
  6440. && (ra[phi->sources[1]]->flags & (ZREG_LOAD|ZREG_STORE)) == 0) {
  6441. /* Store actual type to memory to avoid deoptimization mistakes */
  6442. /* TODO: Alternatively, we may try to update alredy generated deoptimization info */
  6443. zend_jit_store_var_type(&dasm_state, phi->var, STACK_TYPE(stack, phi->var));
  6444. }
  6445. phi = phi->next;
  6446. }
  6447. }
  6448. if (p->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  6449. if ((t->flags & ZEND_JIT_TRACE_USES_INITIAL_IP)
  6450. && !zend_jit_set_ip(&dasm_state, p->opline)) {
  6451. goto jit_failure;
  6452. }
  6453. }
  6454. t->link = ZEND_JIT_TRACE_NUM;
  6455. if (p->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  6456. t->flags |= ZEND_JIT_TRACE_CHECK_INTERRUPT;
  6457. }
  6458. if (!(t->flags & ZEND_JIT_TRACE_LOOP)) {
  6459. const void *timeout_exit_addr = NULL;
  6460. t->flags |= ZEND_JIT_TRACE_LOOP;
  6461. if (trace_buffer->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  6462. if (!(t->flags & ZEND_JIT_TRACE_USES_INITIAL_IP)
  6463. || (ra
  6464. && zend_jit_trace_stack_needs_deoptimization(stack, op_array->last_var + op_array->T))) {
  6465. uint32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
  6466. timeout_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  6467. if (!timeout_exit_addr) {
  6468. goto jit_failure;
  6469. }
  6470. } else {
  6471. timeout_exit_addr = dasm_labels[zend_lbinterrupt_handler];
  6472. }
  6473. }
  6474. zend_jit_trace_end_loop(&dasm_state, 0, timeout_exit_addr); /* jump back to start of the trace loop */
  6475. }
  6476. } else if (p->stop == ZEND_JIT_TRACE_STOP_LINK
  6477. || p->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
  6478. if (!zend_jit_trace_deoptimization(&dasm_state, 0, NULL,
  6479. stack, op_array->last_var + op_array->T, NULL, NULL, NULL, 0)) {
  6480. goto jit_failure;
  6481. }
  6482. if (p->stop == ZEND_JIT_TRACE_STOP_LINK) {
  6483. const void *timeout_exit_addr = NULL;
  6484. t->link = zend_jit_find_trace(p->opline->handler);
  6485. if ((zend_jit_traces[t->link].flags & ZEND_JIT_TRACE_USES_INITIAL_IP)
  6486. && !zend_jit_set_ip(&dasm_state, p->opline)) {
  6487. goto jit_failure;
  6488. }
  6489. if (!parent_trace && zend_jit_trace_uses_initial_ip()) {
  6490. t->flags |= ZEND_JIT_TRACE_USES_INITIAL_IP;
  6491. }
  6492. if (parent_trace
  6493. && (zend_jit_traces[t->link].flags & ZEND_JIT_TRACE_CHECK_INTERRUPT)
  6494. && zend_jit_traces[parent_trace].root == t->link) {
  6495. if (!(zend_jit_traces[t->link].flags & ZEND_JIT_TRACE_USES_INITIAL_IP)) {
  6496. uint32_t exit_point;
  6497. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  6498. SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
  6499. }
  6500. exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
  6501. timeout_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
  6502. if (!timeout_exit_addr) {
  6503. goto jit_failure;
  6504. }
  6505. } else {
  6506. timeout_exit_addr = dasm_labels[zend_lbinterrupt_handler];
  6507. }
  6508. }
  6509. zend_jit_trace_link_to_root(&dasm_state, &zend_jit_traces[t->link], timeout_exit_addr);
  6510. } else {
  6511. zend_jit_trace_return(&dasm_state, 0, NULL);
  6512. }
  6513. } else if (p->stop == ZEND_JIT_TRACE_STOP_RETURN) {
  6514. zend_jit_trace_return(&dasm_state, 0, NULL);
  6515. } else {
  6516. // TODO: not implemented ???
  6517. ZEND_ASSERT(0 && p->stop);
  6518. }
  6519. if (ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) {
  6520. goto jit_failure;
  6521. }
  6522. if (!zend_jit_trace_end(&dasm_state, t)) {
  6523. goto jit_failure;
  6524. }
  6525. handler = dasm_link_and_encode(&dasm_state, NULL, NULL, NULL, NULL, ZSTR_VAL(name), ZEND_JIT_TRACE_NUM,
  6526. parent_trace ? SP_ADJ_JIT : ((zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) ? SP_ADJ_VM : SP_ADJ_RET),
  6527. parent_trace ? SP_ADJ_NONE : SP_ADJ_JIT);
  6528. if (handler) {
  6529. if (p->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL) {
  6530. const zend_op_array *rec_op_array;
  6531. rec_op_array = op_array = trace_buffer->op_array;
  6532. jit_extension =
  6533. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6534. p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
  6535. for (;;p++) {
  6536. if (p->op == ZEND_JIT_TRACE_VM) {
  6537. opline = p->opline;
  6538. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  6539. if (p->op_array == rec_op_array) {
  6540. zend_jit_trace_setup_ret_counter(opline, jit_extension->offset);
  6541. }
  6542. op_array = p->op_array;
  6543. jit_extension =
  6544. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6545. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  6546. op_array = p->op_array;
  6547. jit_extension =
  6548. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6549. } else if (p->op == ZEND_JIT_TRACE_END) {
  6550. break;
  6551. }
  6552. }
  6553. } else if (p->stop == ZEND_JIT_TRACE_STOP_LINK
  6554. || p->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
  6555. if (opline
  6556. && (opline->opcode == ZEND_DO_UCALL
  6557. || opline->opcode == ZEND_DO_FCALL
  6558. || opline->opcode == ZEND_DO_FCALL_BY_NAME
  6559. || opline->opcode == ZEND_YIELD
  6560. || opline->opcode == ZEND_YIELD_FROM
  6561. || opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
  6562. zend_jit_trace_setup_ret_counter(opline, jit_extension->offset);
  6563. }
  6564. if (JIT_G(current_frame)
  6565. && JIT_G(current_frame)->prev) {
  6566. frame = JIT_G(current_frame)->prev;
  6567. do {
  6568. if (frame->call_opline) {
  6569. op_array = &frame->func->op_array;
  6570. jit_extension =
  6571. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6572. zend_jit_trace_setup_ret_counter(frame->call_opline, jit_extension->offset);
  6573. }
  6574. frame = frame->prev;
  6575. } while (frame);
  6576. }
  6577. }
  6578. }
  6579. jit_failure:
  6580. dasm_free(&dasm_state);
  6581. if (name) {
  6582. zend_string_release(name);
  6583. }
  6584. jit_cleanup:
  6585. /* Clean up used op_arrays */
  6586. while (num_op_arrays > 0) {
  6587. op_array = op_arrays[--num_op_arrays];
  6588. jit_extension =
  6589. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  6590. jit_extension->func_info.num = 0;
  6591. jit_extension->func_info.flags &= ZEND_FUNC_JIT_ON_FIRST_EXEC
  6592. | ZEND_FUNC_JIT_ON_PROF_REQUEST
  6593. | ZEND_FUNC_JIT_ON_HOT_COUNTERS
  6594. | ZEND_FUNC_JIT_ON_HOT_TRACE;
  6595. memset(&jit_extension->func_info.ssa, 0, sizeof(zend_func_info) - offsetof(zend_func_info, ssa));
  6596. }
  6597. zend_arena_release(&CG(arena), checkpoint);
  6598. JIT_G(current_frame) = NULL;
  6599. JIT_G(current_trace) = NULL;
  6600. return handler;
  6601. }
  6602. static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_num)
  6603. {
  6604. const void *handler = NULL;
  6605. dasm_State* dasm_state = NULL;
  6606. void *checkpoint;
  6607. char name[32];
  6608. const zend_op *opline;
  6609. uint32_t stack_size;
  6610. zend_jit_trace_stack *stack;
  6611. bool original_handler = 0;
  6612. if (!zend_jit_trace_exit_needs_deoptimization(trace_num, exit_num)) {
  6613. return dasm_labels[zend_lbtrace_escape];
  6614. }
  6615. checkpoint = zend_arena_checkpoint(CG(arena));;
  6616. sprintf(name, "ESCAPE-%d-%d", trace_num, exit_num);
  6617. dasm_init(&dasm_state, DASM_MAXSECTION);
  6618. dasm_setupglobal(&dasm_state, dasm_labels, zend_lb_MAX);
  6619. dasm_setup(&dasm_state, dasm_actions);
  6620. zend_jit_align_func(&dasm_state);
  6621. /* Deoptimization */
  6622. stack_size = zend_jit_traces[trace_num].exit_info[exit_num].stack_size;
  6623. stack = zend_jit_traces[trace_num].stack_map + zend_jit_traces[trace_num].exit_info[exit_num].stack_offset;
  6624. if (!zend_jit_trace_deoptimization(&dasm_state,
  6625. zend_jit_traces[trace_num].exit_info[exit_num].flags,
  6626. zend_jit_traces[trace_num].exit_info[exit_num].opline,
  6627. stack, stack_size, NULL, NULL, NULL, 0)) {
  6628. goto jit_failure;
  6629. }
  6630. opline = zend_jit_traces[trace_num].exit_info[exit_num].opline;
  6631. if (opline) {
  6632. if (opline == zend_jit_traces[zend_jit_traces[trace_num].root].opline) {
  6633. /* prevent endless loop */
  6634. original_handler = 1;
  6635. }
  6636. zend_jit_set_ip_ex(&dasm_state, opline, original_handler);
  6637. }
  6638. zend_jit_trace_return(&dasm_state, original_handler, opline);
  6639. handler = dasm_link_and_encode(&dasm_state, NULL, NULL, NULL, NULL, name, ZEND_JIT_TRACE_NUM, SP_ADJ_JIT, SP_ADJ_NONE);
  6640. jit_failure:
  6641. dasm_free(&dasm_state);
  6642. zend_arena_release(&CG(arena), checkpoint);
  6643. return handler;
  6644. }
  6645. static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace_buffer, const zend_op *opline, size_t offset)
  6646. {
  6647. zend_jit_trace_stop ret;
  6648. const void *handler;
  6649. uint8_t orig_trigger;
  6650. zend_jit_trace_info *t = NULL;
  6651. zend_jit_trace_exit_info exit_info[ZEND_JIT_TRACE_MAX_EXITS];
  6652. bool do_bailout = 0;
  6653. zend_shared_alloc_lock();
  6654. /* Checks under lock */
  6655. if ((ZEND_OP_TRACE_INFO(opline, offset)->trace_flags & ZEND_JIT_TRACE_JITED)) {
  6656. ret = ZEND_JIT_TRACE_STOP_ALREADY_DONE;
  6657. } else if (ZEND_JIT_TRACE_NUM >= JIT_G(max_root_traces)) {
  6658. ret = ZEND_JIT_TRACE_STOP_TOO_MANY_TRACES;
  6659. } else {
  6660. zend_try {
  6661. SHM_UNPROTECT();
  6662. zend_jit_unprotect();
  6663. t = &zend_jit_traces[ZEND_JIT_TRACE_NUM];
  6664. t->id = ZEND_JIT_TRACE_NUM;
  6665. t->root = ZEND_JIT_TRACE_NUM;
  6666. t->parent = 0;
  6667. t->link = 0;
  6668. t->exit_count = 0;
  6669. t->child_count = 0;
  6670. t->stack_map_size = 0;
  6671. t->flags = 0;
  6672. t->polymorphism = 0;
  6673. t->jmp_table_size = 0;
  6674. t->op_array = trace_buffer[0].op_array;
  6675. t->opline = trace_buffer[1].opline;
  6676. t->exit_info = exit_info;
  6677. t->stack_map = NULL;
  6678. orig_trigger = JIT_G(trigger);
  6679. JIT_G(trigger) = ZEND_JIT_ON_HOT_TRACE;
  6680. handler = zend_jit_trace(trace_buffer, 0, 0);
  6681. JIT_G(trigger) = orig_trigger;
  6682. if (handler) {
  6683. zend_jit_trace_exit_info *shared_exit_info = NULL;
  6684. t->exit_info = NULL;
  6685. if (t->exit_count) {
  6686. /* reallocate exit_info into shared memory */
  6687. shared_exit_info = (zend_jit_trace_exit_info*)zend_shared_alloc(
  6688. sizeof(zend_jit_trace_exit_info) * t->exit_count);
  6689. if (!shared_exit_info) {
  6690. if (t->stack_map) {
  6691. efree(t->stack_map);
  6692. t->stack_map = NULL;
  6693. }
  6694. ret = ZEND_JIT_TRACE_STOP_NO_SHM;
  6695. goto exit;
  6696. }
  6697. memcpy(shared_exit_info, exit_info,
  6698. sizeof(zend_jit_trace_exit_info) * t->exit_count);
  6699. t->exit_info = shared_exit_info;
  6700. }
  6701. if (t->stack_map_size) {
  6702. zend_jit_trace_stack *shared_stack_map = (zend_jit_trace_stack*)zend_shared_alloc(t->stack_map_size * sizeof(zend_jit_trace_stack));
  6703. if (!shared_stack_map) {
  6704. ret = ZEND_JIT_TRACE_STOP_NO_SHM;
  6705. goto exit;
  6706. }
  6707. memcpy(shared_stack_map, t->stack_map, t->stack_map_size * sizeof(zend_jit_trace_stack));
  6708. efree(t->stack_map);
  6709. t->stack_map = shared_stack_map;
  6710. }
  6711. t->exit_counters = ZEND_JIT_EXIT_COUNTERS;
  6712. ZEND_JIT_EXIT_COUNTERS += t->exit_count;
  6713. ((zend_op*)opline)->handler = handler;
  6714. ZEND_JIT_TRACE_NUM++;
  6715. ZEND_OP_TRACE_INFO(opline, offset)->trace_flags |= ZEND_JIT_TRACE_JITED;
  6716. ret = ZEND_JIT_TRACE_STOP_COMPILED;
  6717. } else if (t->exit_count >= ZEND_JIT_TRACE_MAX_EXITS ||
  6718. ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) {
  6719. if (t->stack_map) {
  6720. efree(t->stack_map);
  6721. t->stack_map = NULL;
  6722. }
  6723. ret = ZEND_JIT_TRACE_STOP_TOO_MANY_EXITS;
  6724. } else {
  6725. if (t->stack_map) {
  6726. efree(t->stack_map);
  6727. t->stack_map = NULL;
  6728. }
  6729. ret = ZEND_JIT_TRACE_STOP_COMPILER_ERROR;
  6730. }
  6731. exit:;
  6732. } zend_catch {
  6733. do_bailout = 1;
  6734. } zend_end_try();
  6735. zend_jit_protect();
  6736. SHM_PROTECT();
  6737. }
  6738. zend_shared_alloc_unlock();
  6739. if (do_bailout) {
  6740. zend_bailout();
  6741. }
  6742. if ((JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_EXIT_INFO) != 0
  6743. && ret == ZEND_JIT_TRACE_STOP_COMPILED
  6744. && t->exit_count > 0) {
  6745. zend_jit_dump_exit_info(t);
  6746. }
  6747. return ret;
  6748. }
  6749. static void zend_jit_blacklist_root_trace(const zend_op *opline, size_t offset)
  6750. {
  6751. zend_shared_alloc_lock();
  6752. if (!(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags & ZEND_JIT_TRACE_BLACKLISTED)) {
  6753. SHM_UNPROTECT();
  6754. zend_jit_unprotect();
  6755. ((zend_op*)opline)->handler =
  6756. ZEND_OP_TRACE_INFO(opline, offset)->orig_handler;
  6757. ZEND_OP_TRACE_INFO(opline, offset)->trace_flags |= ZEND_JIT_TRACE_BLACKLISTED;
  6758. zend_jit_protect();
  6759. SHM_PROTECT();
  6760. }
  6761. zend_shared_alloc_unlock();
  6762. }
  6763. static bool zend_jit_trace_is_bad_root(const zend_op *opline, zend_jit_trace_stop stop, size_t offset)
  6764. {
  6765. const zend_op **cache_opline = JIT_G(bad_root_cache_opline);
  6766. uint8_t *cache_count = JIT_G(bad_root_cache_count);
  6767. uint8_t *cache_stop = JIT_G(bad_root_cache_stop);
  6768. uint32_t cache_slot = JIT_G(bad_root_slot);
  6769. uint32_t i;
  6770. for (i = 0; i < ZEND_JIT_TRACE_BAD_ROOT_SLOTS; i++) {
  6771. if (cache_opline[i] == opline) {
  6772. if (cache_count[i] >= JIT_G(blacklist_root_trace) - 1) {
  6773. cache_opline[i] = NULL;
  6774. return 1;
  6775. } else {
  6776. #if 0
  6777. if (ZEND_OP_TRACE_INFO(opline, offset)->counter) {
  6778. *ZEND_OP_TRACE_INFO(opline, offset)->counter =
  6779. random() % ZEND_JIT_TRACE_COUNTER_MAX;
  6780. }
  6781. #endif
  6782. cache_count[i]++;
  6783. cache_stop[i] = stop;
  6784. return 0;
  6785. }
  6786. }
  6787. }
  6788. i = cache_slot;
  6789. cache_opline[i] = opline;
  6790. cache_count[i] = 1;
  6791. cache_stop[i] = stop;
  6792. cache_slot = (i + 1) % ZEND_JIT_TRACE_BAD_ROOT_SLOTS;
  6793. JIT_G(bad_root_slot) = cache_slot;
  6794. return 0;
  6795. }
  6796. static void zend_jit_dump_trace(zend_jit_trace_rec *trace_buffer, zend_ssa *tssa)
  6797. {
  6798. zend_jit_trace_rec *p = trace_buffer;
  6799. const zend_op_array *op_array;
  6800. const zend_op *opline;
  6801. uint32_t level = 1 + trace_buffer[0].level;
  6802. int idx, len, i, v, vars_count, call_level;
  6803. ZEND_ASSERT(p->op == ZEND_JIT_TRACE_START);
  6804. op_array = p->op_array;
  6805. p += ZEND_JIT_TRACE_START_REC_SIZE;
  6806. idx = 0;
  6807. call_level = 0;
  6808. if (tssa && tssa->var_info) {
  6809. if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
  6810. vars_count = op_array->last_var;
  6811. } else {
  6812. vars_count = op_array->last_var + op_array->T;
  6813. }
  6814. for (i = 0; i < vars_count; i++) {
  6815. if (tssa->vars[i].use_chain >= 0 || tssa->vars[i].phi_use_chain) {
  6816. fprintf(stderr, " %*c;", level, ' ');
  6817. zend_dump_ssa_var(op_array, tssa, i, 0, i, ZEND_DUMP_RC_INFERENCE);
  6818. fprintf(stderr, "\n");
  6819. }
  6820. }
  6821. if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
  6822. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
  6823. || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
  6824. zend_ssa_phi *p = tssa->blocks[1].phis;
  6825. fprintf(stderr, "LOOP:\n");
  6826. while (p) {
  6827. fprintf(stderr, " ;");
  6828. zend_dump_ssa_var(op_array, tssa, p->ssa_var, 0, p->var, ZEND_DUMP_RC_INFERENCE);
  6829. fprintf(stderr, " = Phi(");
  6830. zend_dump_ssa_var(op_array, tssa, p->sources[0], 0, p->var, ZEND_DUMP_RC_INFERENCE);
  6831. fprintf(stderr, ", ");
  6832. zend_dump_ssa_var(op_array, tssa, p->sources[1], 0, p->var, ZEND_DUMP_RC_INFERENCE);
  6833. fprintf(stderr, ")\n");
  6834. p = p->next;
  6835. }
  6836. }
  6837. }
  6838. while (1) {
  6839. if (p->op == ZEND_JIT_TRACE_VM) {
  6840. uint8_t op1_type, op2_type, op3_type;
  6841. opline = p->opline;
  6842. fprintf(stderr, "%04d%*c",
  6843. (int)(opline - op_array->opcodes),
  6844. level, ' ');
  6845. zend_dump_op(op_array, NULL, opline, ZEND_DUMP_RC_INFERENCE, tssa, (tssa && tssa->ops) ? tssa->ops + idx : NULL);
  6846. op1_type = p->op1_type;
  6847. op2_type = p->op2_type;
  6848. op3_type = p->op3_type;
  6849. if (op1_type != IS_UNKNOWN || op2_type != IS_UNKNOWN || op3_type != IS_UNKNOWN) {
  6850. fprintf(stderr, " ;");
  6851. if (op1_type != IS_UNKNOWN) {
  6852. const char *ref = (op1_type & IS_TRACE_INDIRECT) ?
  6853. ((op1_type & IS_TRACE_REFERENCE) ? "*&" : "*") :
  6854. ((op1_type & IS_TRACE_REFERENCE) ? "&" : "");
  6855. if ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE) {
  6856. p++;
  6857. fprintf(stderr, " op1(%sobject of class %s)", ref,
  6858. ZSTR_VAL(p->ce->name));
  6859. } else {
  6860. const char *type = (op1_type == 0) ? "undef" : zend_get_type_by_const(op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED));
  6861. fprintf(stderr, " op1(%s%s%s)", ref, (op1_type & IS_TRACE_PACKED) ? "packed " : "", type);
  6862. }
  6863. }
  6864. if (op2_type != IS_UNKNOWN) {
  6865. const char *ref = (op2_type & IS_TRACE_INDIRECT) ?
  6866. ((op2_type & IS_TRACE_REFERENCE) ? "*&" : "*") :
  6867. ((op2_type & IS_TRACE_REFERENCE) ? "&" : "");
  6868. if ((p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
  6869. p++;
  6870. fprintf(stderr, " op2(%sobject of class %s)", ref,
  6871. ZSTR_VAL(p->ce->name));
  6872. } else {
  6873. const char *type = (op2_type == 0) ? "undef" : zend_get_type_by_const(op2_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT));
  6874. fprintf(stderr, " op2(%s%s)", ref, type);
  6875. }
  6876. }
  6877. if (op3_type != IS_UNKNOWN) {
  6878. const char *ref = (op3_type & IS_TRACE_INDIRECT) ?
  6879. ((op3_type & IS_TRACE_REFERENCE) ? "*&" : "*") :
  6880. ((op3_type & IS_TRACE_REFERENCE) ? "&" : "");
  6881. const char *type = (op3_type == 0) ? "undef" : zend_get_type_by_const(op3_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT));
  6882. fprintf(stderr, " op3(%s%s)", ref, type);
  6883. }
  6884. }
  6885. if ((p+1)->op == ZEND_JIT_TRACE_VAL_INFO) {
  6886. uint8_t val_type;
  6887. const char *type;
  6888. if (op1_type == IS_UNKNOWN && op2_type == IS_UNKNOWN && op3_type == IS_UNKNOWN) {
  6889. fprintf(stderr, " ;");
  6890. }
  6891. p++;
  6892. val_type = p->op1_type;
  6893. if (val_type == IS_UNDEF) {
  6894. type = "undef";
  6895. } else if (val_type == IS_REFERENCE) {
  6896. type = "ref";
  6897. } else {
  6898. type = zend_get_type_by_const(val_type);
  6899. }
  6900. fprintf(stderr, " val(%s)", type);
  6901. }
  6902. fprintf(stderr, "\n");
  6903. idx++;
  6904. len = zend_jit_trace_op_len(opline);
  6905. while (len > 1) {
  6906. opline++;
  6907. fprintf(stderr, "%04d%*c;",
  6908. (int)(opline - op_array->opcodes),
  6909. level, ' ');
  6910. zend_dump_op(op_array, NULL, opline, ZEND_DUMP_RC_INFERENCE, tssa, (tssa && tssa->ops) ? tssa->ops + idx : NULL);
  6911. idx++;
  6912. len--;
  6913. fprintf(stderr, "\n");
  6914. }
  6915. } else if (p->op == ZEND_JIT_TRACE_ENTER) {
  6916. op_array = p->op_array;
  6917. fprintf(stderr, " %*c>enter %s%s%s\n",
  6918. level, ' ',
  6919. op_array->scope ? ZSTR_VAL(op_array->scope->name) : "",
  6920. op_array->scope ? "::" : "",
  6921. op_array->function_name ?
  6922. ZSTR_VAL(op_array->function_name) :
  6923. ZSTR_VAL(op_array->filename));
  6924. level++;
  6925. if (tssa && tssa->var_info) {
  6926. call_level++;
  6927. v = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  6928. vars_count = op_array->last_var;
  6929. for (i = 0; i < vars_count; i++, v++) {
  6930. if (tssa->vars[v].use_chain >= 0 || tssa->vars[v].phi_use_chain) {
  6931. fprintf(stderr, " %*c;", level, ' ');
  6932. zend_dump_ssa_var(op_array, tssa, v, 0, i, ZEND_DUMP_RC_INFERENCE);
  6933. fprintf(stderr, "\n");
  6934. }
  6935. }
  6936. }
  6937. } else if (p->op == ZEND_JIT_TRACE_BACK) {
  6938. op_array = p->op_array;
  6939. level--;
  6940. fprintf(stderr, " %*c<back %s%s%s\n",
  6941. level, ' ',
  6942. op_array->scope ? ZSTR_VAL(op_array->scope->name) : "",
  6943. op_array->scope ? "::" : "",
  6944. op_array->function_name ?
  6945. ZSTR_VAL(op_array->function_name) :
  6946. ZSTR_VAL(op_array->filename));
  6947. if (tssa && tssa->var_info) {
  6948. if (call_level == 0) {
  6949. v = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
  6950. vars_count = op_array->last_var + op_array->T;
  6951. for (i = 0; i < vars_count; i++, v++) {
  6952. if (tssa->vars[v].use_chain >= 0 || tssa->vars[v].phi_use_chain) {
  6953. fprintf(stderr, " %*c;", level, ' ');
  6954. zend_dump_ssa_var(op_array, tssa, v, 0, i, ZEND_DUMP_RC_INFERENCE);
  6955. fprintf(stderr, "\n");
  6956. }
  6957. }
  6958. } else {
  6959. call_level--;
  6960. }
  6961. }
  6962. } else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
  6963. if (p->func != (zend_function*)&zend_pass_function) {
  6964. fprintf(stderr, (p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL) ? " %*c>fake_init %s%s%s\n" : " %*c>init %s%s%s\n",
  6965. level, ' ',
  6966. (p->func && p->func->common.scope) ? ZSTR_VAL(p->func->common.scope->name) : "",
  6967. (p->func && p->func->common.scope) ? "::" : "",
  6968. p->func ? ZSTR_VAL(p->func->common.function_name) : "???");
  6969. } else {
  6970. fprintf(stderr, " %*c>skip\n",
  6971. level, ' ');
  6972. }
  6973. } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
  6974. if (p->func != (zend_function*)&zend_pass_function) {
  6975. fprintf(stderr, " %*c>call %s%s%s\n",
  6976. level, ' ',
  6977. p->func->common.scope ? ZSTR_VAL(p->func->common.scope->name) : "",
  6978. p->func->common.scope ? "::" : "",
  6979. ZSTR_VAL(p->func->common.function_name));
  6980. } else {
  6981. fprintf(stderr, " %*c>skip\n",
  6982. level, ' ');
  6983. }
  6984. } else if (p->op == ZEND_JIT_TRACE_END) {
  6985. break;
  6986. }
  6987. p++;
  6988. }
  6989. }
  6990. static void zend_jit_dump_exit_info(zend_jit_trace_info *t)
  6991. {
  6992. int i, j;
  6993. fprintf(stderr, "---- TRACE %d exit info\n", t->id);
  6994. for (i = 0; i < t->exit_count; i++) {
  6995. const zend_op_array *op_array = t->exit_info[i].op_array;
  6996. uint32_t stack_size = t->exit_info[i].stack_size;
  6997. zend_jit_trace_stack *stack = t->stack_map + t->exit_info[i].stack_offset;
  6998. fprintf(stderr, " exit_%d:", i);
  6999. if (t->exit_info[i].opline) {
  7000. fprintf(stderr, " %04d/", (int)(t->exit_info[i].opline - op_array->opcodes));
  7001. } else {
  7002. fprintf(stderr, " ----/");
  7003. }
  7004. if (t->exit_info[i].stack_size) {
  7005. fprintf(stderr, "%04d/%d", t->exit_info[i].stack_offset, t->exit_info[i].stack_size);
  7006. } else {
  7007. fprintf(stderr, "----/0");
  7008. }
  7009. if (t->exit_info[i].flags & ZEND_JIT_EXIT_TO_VM) {
  7010. fprintf(stderr, "/VM");
  7011. }
  7012. if (t->exit_info[i].flags & ZEND_JIT_EXIT_RESTORE_CALL) {
  7013. fprintf(stderr, "/CALL");
  7014. }
  7015. if (t->exit_info[i].flags & (ZEND_JIT_EXIT_POLYMORPHISM|ZEND_JIT_EXIT_METHOD_CALL|ZEND_JIT_EXIT_CLOSURE_CALL)) {
  7016. fprintf(stderr, "/POLY");
  7017. }
  7018. if (t->exit_info[i].flags & ZEND_JIT_EXIT_FREE_OP1) {
  7019. fprintf(stderr, "/FREE_OP1");
  7020. }
  7021. if (t->exit_info[i].flags & ZEND_JIT_EXIT_FREE_OP2) {
  7022. fprintf(stderr, "/FREE_OP2");
  7023. }
  7024. for (j = 0; j < stack_size; j++) {
  7025. zend_uchar type = STACK_TYPE(stack, j);
  7026. if (type != IS_UNKNOWN) {
  7027. fprintf(stderr, " ");
  7028. zend_dump_var(op_array, (j < op_array->last_var) ? IS_CV : 0, j);
  7029. fprintf(stderr, ":");
  7030. if (type == IS_UNDEF) {
  7031. fprintf(stderr, "undef");
  7032. } else {
  7033. fprintf(stderr, "%s", zend_get_type_by_const(type));
  7034. }
  7035. if (STACK_REG(stack, j) != ZREG_NONE) {
  7036. if (STACK_REG(stack, j) < ZREG_NUM) {
  7037. fprintf(stderr, "(%s)", zend_reg_name[STACK_REG(stack, j)]);
  7038. } else if (STACK_REG(stack, j) == ZREG_THIS) {
  7039. fprintf(stderr, "(this)");
  7040. } else if (STACK_REG(stack, j) == ZREG_ZVAL_TRY_ADDREF) {
  7041. fprintf(stderr, "(zval_try_addref)");
  7042. } else {
  7043. fprintf(stderr, "(const_%d)", STACK_REG(stack, j) - ZREG_NUM);
  7044. }
  7045. }
  7046. } else if (STACK_REG(stack, j) == ZREG_ZVAL_TRY_ADDREF) {
  7047. fprintf(stderr, " ");
  7048. zend_dump_var(op_array, (j < op_array->last_var) ? IS_CV : 0, j);
  7049. fprintf(stderr, ":unknown(zval_try_addref)");
  7050. } else if (STACK_REG(stack, j) == ZREG_ZVAL_COPY_GPR0) {
  7051. fprintf(stderr, " ");
  7052. zend_dump_var(op_array, (j < op_array->last_var) ? IS_CV : 0, j);
  7053. fprintf(stderr, ":unknown(zval_copy(%s))", zend_reg_name[ZREG_COPY]);
  7054. }
  7055. }
  7056. fprintf(stderr, "\n");
  7057. }
  7058. }
  7059. int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const zend_op *opline)
  7060. {
  7061. const zend_op *orig_opline;
  7062. zend_jit_trace_stop stop;
  7063. int ret = 0;
  7064. zend_op_array *op_array;
  7065. zend_jit_op_array_trace_extension *jit_extension;
  7066. size_t offset;
  7067. uint32_t trace_num;
  7068. zend_jit_trace_rec trace_buffer[ZEND_JIT_TRACE_MAX_LENGTH];
  7069. ZEND_ASSERT(EX(func)->type == ZEND_USER_FUNCTION);
  7070. ZEND_ASSERT(opline >= EX(func)->op_array.opcodes &&
  7071. opline < EX(func)->op_array.opcodes + EX(func)->op_array.last);
  7072. repeat:
  7073. trace_num = ZEND_JIT_TRACE_NUM;
  7074. orig_opline = opline;
  7075. op_array = &EX(func)->op_array;
  7076. jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  7077. offset = jit_extension->offset;
  7078. EX(opline) = opline;
  7079. /* Lock-free check if the root trace was already JIT-ed or blacklist-ed in another process */
  7080. if (ZEND_OP_TRACE_INFO(opline, offset)->trace_flags & (ZEND_JIT_TRACE_JITED|ZEND_JIT_TRACE_BLACKLISTED)) {
  7081. return 0;
  7082. }
  7083. if (JIT_G(tracing)) {
  7084. ++(*ZEND_OP_TRACE_INFO(opline, offset)->counter);
  7085. return 0;
  7086. }
  7087. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_START) {
  7088. fprintf(stderr, "---- TRACE %d start (%s) %s%s%s() %s:%d\n",
  7089. trace_num,
  7090. zend_jit_trace_star_desc(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags),
  7091. EX(func)->op_array.scope ? ZSTR_VAL(EX(func)->op_array.scope->name) : "",
  7092. EX(func)->op_array.scope ? "::" : "",
  7093. EX(func)->op_array.function_name ?
  7094. ZSTR_VAL(EX(func)->op_array.function_name) : "$main",
  7095. ZSTR_VAL(EX(func)->op_array.filename),
  7096. opline->lineno);
  7097. }
  7098. if (ZEND_JIT_TRACE_NUM >= JIT_G(max_root_traces)) {
  7099. stop = ZEND_JIT_TRACE_STOP_TOO_MANY_TRACES;
  7100. goto abort;
  7101. }
  7102. JIT_G(tracing) = 1;
  7103. stop = zend_jit_trace_execute(execute_data, opline, trace_buffer,
  7104. ZEND_OP_TRACE_INFO(opline, offset)->trace_flags & ZEND_JIT_TRACE_START_MASK, 0);
  7105. JIT_G(tracing) = 0;
  7106. if (stop & ZEND_JIT_TRACE_HALT) {
  7107. ret = -1;
  7108. }
  7109. stop &= ~ZEND_JIT_TRACE_HALT;
  7110. if (UNEXPECTED(trace_buffer[1].opline != orig_opline)) {
  7111. orig_opline = trace_buffer[1].opline;
  7112. op_array = (zend_op_array*)trace_buffer[0].op_array;
  7113. jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  7114. offset = jit_extension->offset;
  7115. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_START) {
  7116. const zend_op_array *op_array = trace_buffer[0].op_array;
  7117. const zend_op *opline = trace_buffer[1].opline;
  7118. zend_jit_op_array_trace_extension *jit_extension =
  7119. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  7120. size_t offset = jit_extension->offset;
  7121. fprintf(stderr, "---- TRACE %d start (%s) %s%s%s() %s:%d\n",
  7122. trace_num,
  7123. zend_jit_trace_star_desc(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags),
  7124. op_array->scope ? ZSTR_VAL(op_array->scope->name) : "",
  7125. op_array->scope ? "::" : "",
  7126. op_array->function_name ?
  7127. ZSTR_VAL(op_array->function_name) : "$main",
  7128. ZSTR_VAL(op_array->filename),
  7129. opline->lineno);
  7130. }
  7131. }
  7132. if (UNEXPECTED(JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BYTECODE)) {
  7133. zend_jit_dump_trace(trace_buffer, NULL);
  7134. }
  7135. if (ZEND_JIT_TRACE_STOP_OK(stop)) {
  7136. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_STOP) {
  7137. if (stop == ZEND_JIT_TRACE_STOP_LINK) {
  7138. uint32_t idx = trace_buffer[1].last;
  7139. uint32_t link_to = zend_jit_find_trace(trace_buffer[idx].opline->handler);
  7140. fprintf(stderr, "---- TRACE %d stop (link to %d)\n",
  7141. trace_num,
  7142. link_to);
  7143. } else {
  7144. fprintf(stderr, "---- TRACE %d stop (%s)\n",
  7145. trace_num,
  7146. zend_jit_trace_stop_description[stop]);
  7147. }
  7148. }
  7149. stop = zend_jit_compile_root_trace(trace_buffer, orig_opline, offset);
  7150. if (EXPECTED(ZEND_JIT_TRACE_STOP_DONE(stop))) {
  7151. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_COMPILED) {
  7152. fprintf(stderr, "---- TRACE %d %s\n",
  7153. trace_num,
  7154. zend_jit_trace_stop_description[stop]);
  7155. }
  7156. } else {
  7157. goto abort;
  7158. }
  7159. } else {
  7160. abort:
  7161. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_ABORT) {
  7162. fprintf(stderr, "---- TRACE %d abort (%s)\n",
  7163. trace_num,
  7164. zend_jit_trace_stop_description[stop]);
  7165. }
  7166. if (!ZEND_JIT_TRACE_STOP_MAY_RECOVER(stop)
  7167. || zend_jit_trace_is_bad_root(orig_opline, stop, offset)) {
  7168. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BLACKLIST) {
  7169. fprintf(stderr, "---- TRACE %d blacklisted\n",
  7170. trace_num);
  7171. }
  7172. zend_jit_blacklist_root_trace(orig_opline, offset);
  7173. }
  7174. if (ZEND_JIT_TRACE_STOP_REPEAT(stop)) {
  7175. execute_data = EG(current_execute_data);
  7176. opline = EX(opline);
  7177. goto repeat;
  7178. }
  7179. }
  7180. if (JIT_G(debug) & (ZEND_JIT_DEBUG_TRACE_STOP|ZEND_JIT_DEBUG_TRACE_ABORT|ZEND_JIT_DEBUG_TRACE_COMPILED|ZEND_JIT_DEBUG_TRACE_BLACKLIST)) {
  7181. fprintf(stderr, "\n");
  7182. }
  7183. return ret;
  7184. }
  7185. static void zend_jit_blacklist_trace_exit(uint32_t trace_num, uint32_t exit_num)
  7186. {
  7187. const void *handler;
  7188. bool do_bailout = 0;
  7189. zend_shared_alloc_lock();
  7190. if (!(zend_jit_traces[trace_num].exit_info[exit_num].flags & (ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED))) {
  7191. SHM_UNPROTECT();
  7192. zend_jit_unprotect();
  7193. zend_try {
  7194. handler = zend_jit_trace_exit_to_vm(trace_num, exit_num);
  7195. if (handler) {
  7196. zend_jit_link_side_trace(
  7197. zend_jit_traces[trace_num].code_start,
  7198. zend_jit_traces[trace_num].code_size,
  7199. zend_jit_traces[trace_num].jmp_table_size,
  7200. exit_num,
  7201. handler);
  7202. }
  7203. zend_jit_traces[trace_num].exit_info[exit_num].flags |= ZEND_JIT_EXIT_BLACKLISTED;
  7204. } zend_catch {
  7205. do_bailout = 1;
  7206. } zend_end_try();
  7207. zend_jit_protect();
  7208. SHM_PROTECT();
  7209. }
  7210. zend_shared_alloc_unlock();
  7211. if (do_bailout) {
  7212. zend_bailout();
  7213. }
  7214. }
  7215. static bool zend_jit_trace_exit_is_bad(uint32_t trace_num, uint32_t exit_num)
  7216. {
  7217. uint8_t *counter = JIT_G(exit_counters) +
  7218. zend_jit_traces[trace_num].exit_counters + exit_num;
  7219. if (*counter + 1 >= JIT_G(hot_side_exit) + JIT_G(blacklist_side_trace)) {
  7220. return 1;
  7221. }
  7222. (*counter)++;
  7223. return 0;
  7224. }
  7225. static bool zend_jit_trace_exit_is_hot(uint32_t trace_num, uint32_t exit_num)
  7226. {
  7227. uint8_t *counter = JIT_G(exit_counters) +
  7228. zend_jit_traces[trace_num].exit_counters + exit_num;
  7229. if (*counter + 1 >= JIT_G(hot_side_exit)) {
  7230. return 1;
  7231. }
  7232. (*counter)++;
  7233. return 0;
  7234. }
  7235. static zend_jit_trace_stop zend_jit_compile_side_trace(zend_jit_trace_rec *trace_buffer, uint32_t parent_num, uint32_t exit_num, uint32_t polymorphism)
  7236. {
  7237. zend_jit_trace_stop ret;
  7238. const void *handler;
  7239. uint8_t orig_trigger;
  7240. zend_jit_trace_info *t;
  7241. zend_jit_trace_exit_info exit_info[ZEND_JIT_TRACE_MAX_EXITS];
  7242. bool do_bailout = 0;
  7243. zend_shared_alloc_lock();
  7244. /* Checks under lock */
  7245. if (zend_jit_traces[parent_num].exit_info[exit_num].flags & (ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED)) {
  7246. ret = ZEND_JIT_TRACE_STOP_ALREADY_DONE;
  7247. } else if (ZEND_JIT_TRACE_NUM >= JIT_G(max_root_traces)) {
  7248. ret = ZEND_JIT_TRACE_STOP_TOO_MANY_TRACES;
  7249. } else if (zend_jit_traces[zend_jit_traces[parent_num].root].child_count >= JIT_G(max_side_traces)) {
  7250. ret = ZEND_JIT_TRACE_STOP_TOO_MANY_CHILDREN;
  7251. } else {
  7252. SHM_UNPROTECT();
  7253. zend_jit_unprotect();
  7254. zend_try {
  7255. t = &zend_jit_traces[ZEND_JIT_TRACE_NUM];
  7256. t->id = ZEND_JIT_TRACE_NUM;
  7257. t->root = zend_jit_traces[parent_num].root;
  7258. t->parent = parent_num;
  7259. t->link = 0;
  7260. t->exit_count = 0;
  7261. t->child_count = 0;
  7262. t->stack_map_size = 0;
  7263. t->flags = 0;
  7264. t->polymorphism = polymorphism;
  7265. t->jmp_table_size = 0;
  7266. t->opline = NULL;
  7267. t->exit_info = exit_info;
  7268. t->stack_map = NULL;
  7269. orig_trigger = JIT_G(trigger);
  7270. JIT_G(trigger) = ZEND_JIT_ON_HOT_TRACE;
  7271. handler = zend_jit_trace(trace_buffer, parent_num, exit_num);
  7272. JIT_G(trigger) = orig_trigger;
  7273. if (handler) {
  7274. zend_jit_trace_exit_info *shared_exit_info = NULL;
  7275. t->exit_info = NULL;
  7276. if (t->exit_count) {
  7277. /* reallocate exit_info into shared memory */
  7278. shared_exit_info = (zend_jit_trace_exit_info*)zend_shared_alloc(
  7279. sizeof(zend_jit_trace_exit_info) * t->exit_count);
  7280. if (!shared_exit_info) {
  7281. if (t->stack_map) {
  7282. efree(t->stack_map);
  7283. t->stack_map = NULL;
  7284. }
  7285. ret = ZEND_JIT_TRACE_STOP_NO_SHM;
  7286. goto exit;
  7287. }
  7288. memcpy(shared_exit_info, exit_info,
  7289. sizeof(zend_jit_trace_exit_info) * t->exit_count);
  7290. t->exit_info = shared_exit_info;
  7291. }
  7292. if (t->stack_map_size) {
  7293. zend_jit_trace_stack *shared_stack_map = (zend_jit_trace_stack*)zend_shared_alloc(t->stack_map_size * sizeof(zend_jit_trace_stack));
  7294. if (!shared_stack_map) {
  7295. efree(t->stack_map);
  7296. ret = ZEND_JIT_TRACE_STOP_NO_SHM;
  7297. goto exit;
  7298. }
  7299. memcpy(shared_stack_map, t->stack_map, t->stack_map_size * sizeof(zend_jit_trace_stack));
  7300. efree(t->stack_map);
  7301. t->stack_map = shared_stack_map;
  7302. }
  7303. zend_jit_link_side_trace(
  7304. zend_jit_traces[parent_num].code_start,
  7305. zend_jit_traces[parent_num].code_size,
  7306. zend_jit_traces[parent_num].jmp_table_size,
  7307. exit_num,
  7308. handler);
  7309. t->exit_counters = ZEND_JIT_EXIT_COUNTERS;
  7310. ZEND_JIT_EXIT_COUNTERS += t->exit_count;
  7311. zend_jit_traces[zend_jit_traces[parent_num].root].child_count++;
  7312. ZEND_JIT_TRACE_NUM++;
  7313. zend_jit_traces[parent_num].exit_info[exit_num].flags |= ZEND_JIT_EXIT_JITED;
  7314. ret = ZEND_JIT_TRACE_STOP_COMPILED;
  7315. } else if (t->exit_count >= ZEND_JIT_TRACE_MAX_EXITS ||
  7316. ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) {
  7317. if (t->stack_map) {
  7318. efree(t->stack_map);
  7319. t->stack_map = NULL;
  7320. }
  7321. ret = ZEND_JIT_TRACE_STOP_TOO_MANY_EXITS;
  7322. } else {
  7323. if (t->stack_map) {
  7324. efree(t->stack_map);
  7325. t->stack_map = NULL;
  7326. }
  7327. ret = ZEND_JIT_TRACE_STOP_COMPILER_ERROR;
  7328. }
  7329. exit:;
  7330. } zend_catch {
  7331. do_bailout = 1;
  7332. } zend_end_try();
  7333. zend_jit_protect();
  7334. SHM_PROTECT();
  7335. }
  7336. zend_shared_alloc_unlock();
  7337. if (do_bailout) {
  7338. zend_bailout();
  7339. }
  7340. if ((JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_EXIT_INFO) != 0
  7341. && ret == ZEND_JIT_TRACE_STOP_COMPILED
  7342. && t->exit_count > 0) {
  7343. zend_jit_dump_exit_info(t);
  7344. }
  7345. return ret;
  7346. }
  7347. int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint32_t parent_num, uint32_t exit_num)
  7348. {
  7349. zend_jit_trace_stop stop;
  7350. int ret = 0;
  7351. uint32_t trace_num;
  7352. zend_jit_trace_rec trace_buffer[ZEND_JIT_TRACE_MAX_LENGTH];
  7353. uint32_t is_megamorphic = 0;
  7354. uint32_t polymorphism = 0;
  7355. trace_num = ZEND_JIT_TRACE_NUM;
  7356. /* Lock-free check if the side trace was already JIT-ed or blacklist-ed in another process */
  7357. if (zend_jit_traces[parent_num].exit_info[exit_num].flags & (ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED)) {
  7358. return 0;
  7359. }
  7360. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_START) {
  7361. fprintf(stderr, "---- TRACE %d start (side trace %d/%d) %s%s%s() %s:%d\n",
  7362. trace_num, parent_num, exit_num,
  7363. EX(func)->op_array.scope ? ZSTR_VAL(EX(func)->op_array.scope->name) : "",
  7364. EX(func)->op_array.scope ? "::" : "",
  7365. EX(func)->op_array.function_name ?
  7366. ZSTR_VAL(EX(func)->op_array.function_name) : "$main",
  7367. ZSTR_VAL(EX(func)->op_array.filename),
  7368. EX(opline)->lineno);
  7369. }
  7370. if (ZEND_JIT_TRACE_NUM >= JIT_G(max_root_traces)) {
  7371. stop = ZEND_JIT_TRACE_STOP_TOO_MANY_TRACES;
  7372. goto abort;
  7373. }
  7374. if (zend_jit_traces[zend_jit_traces[parent_num].root].child_count >= JIT_G(max_side_traces)) {
  7375. stop = ZEND_JIT_TRACE_STOP_TOO_MANY_CHILDREN;
  7376. goto abort;
  7377. }
  7378. if (JIT_G(max_polymorphic_calls) > 0) {
  7379. if ((zend_jit_traces[parent_num].exit_info[exit_num].flags & (ZEND_JIT_EXIT_METHOD_CALL|ZEND_JIT_EXIT_CLOSURE_CALL))
  7380. || ((zend_jit_traces[parent_num].exit_info[exit_num].flags & ZEND_JIT_EXIT_POLYMORPHISM)
  7381. && EX(call))) {
  7382. if (zend_jit_traces[parent_num].polymorphism >= JIT_G(max_polymorphic_calls) - 1) {
  7383. is_megamorphic = zend_jit_traces[parent_num].exit_info[exit_num].flags &
  7384. (ZEND_JIT_EXIT_METHOD_CALL | ZEND_JIT_EXIT_CLOSURE_CALL | ZEND_JIT_EXIT_POLYMORPHISM);
  7385. } else if (!zend_jit_traces[parent_num].polymorphism) {
  7386. polymorphism = 1;
  7387. } else if (exit_num == 0) {
  7388. polymorphism = zend_jit_traces[parent_num].polymorphism + 1;
  7389. }
  7390. }
  7391. }
  7392. JIT_G(tracing) = 1;
  7393. stop = zend_jit_trace_execute(execute_data, EX(opline), trace_buffer, ZEND_JIT_TRACE_START_SIDE, is_megamorphic);
  7394. JIT_G(tracing) = 0;
  7395. if (stop & ZEND_JIT_TRACE_HALT) {
  7396. ret = -1;
  7397. }
  7398. stop &= ~ZEND_JIT_TRACE_HALT;
  7399. if (UNEXPECTED(trace_buffer->start != ZEND_JIT_TRACE_START_SIDE)) {
  7400. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_START) {
  7401. const zend_op_array *op_array = trace_buffer[0].op_array;
  7402. const zend_op *opline = trace_buffer[1].opline;
  7403. zend_jit_op_array_trace_extension *jit_extension =
  7404. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  7405. size_t offset = jit_extension->offset;
  7406. fprintf(stderr, "---- TRACE %d start (%s) %s%s%s() %s:%d\n",
  7407. trace_num,
  7408. zend_jit_trace_star_desc(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags),
  7409. op_array->scope ? ZSTR_VAL(op_array->scope->name) : "",
  7410. op_array->scope ? "::" : "",
  7411. op_array->function_name ?
  7412. ZSTR_VAL(op_array->function_name) : "$main",
  7413. ZSTR_VAL(op_array->filename),
  7414. opline->lineno);
  7415. }
  7416. }
  7417. if (UNEXPECTED(JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BYTECODE)) {
  7418. zend_jit_dump_trace(trace_buffer, NULL);
  7419. }
  7420. if (ZEND_JIT_TRACE_STOP_OK(stop)) {
  7421. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_STOP) {
  7422. if (stop == ZEND_JIT_TRACE_STOP_LINK) {
  7423. uint32_t idx = trace_buffer[1].last;
  7424. uint32_t link_to = zend_jit_find_trace(trace_buffer[idx].opline->handler);;
  7425. fprintf(stderr, "---- TRACE %d stop (link to %d)\n",
  7426. trace_num,
  7427. link_to);
  7428. } else {
  7429. fprintf(stderr, "---- TRACE %d stop (%s)\n",
  7430. trace_num,
  7431. zend_jit_trace_stop_description[stop]);
  7432. }
  7433. }
  7434. if (EXPECTED(trace_buffer->start == ZEND_JIT_TRACE_START_SIDE)) {
  7435. stop = zend_jit_compile_side_trace(trace_buffer, parent_num, exit_num, polymorphism);
  7436. } else {
  7437. const zend_op_array *op_array = trace_buffer[0].op_array;
  7438. zend_jit_op_array_trace_extension *jit_extension =
  7439. (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  7440. const zend_op *opline = trace_buffer[1].opline;
  7441. stop = zend_jit_compile_root_trace(trace_buffer, opline, jit_extension->offset);
  7442. }
  7443. if (EXPECTED(ZEND_JIT_TRACE_STOP_DONE(stop))) {
  7444. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_COMPILED) {
  7445. fprintf(stderr, "---- TRACE %d %s\n",
  7446. trace_num,
  7447. zend_jit_trace_stop_description[stop]);
  7448. }
  7449. } else {
  7450. goto abort;
  7451. }
  7452. } else {
  7453. abort:
  7454. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_ABORT) {
  7455. fprintf(stderr, "---- TRACE %d abort (%s)\n",
  7456. trace_num,
  7457. zend_jit_trace_stop_description[stop]);
  7458. }
  7459. if (!ZEND_JIT_TRACE_STOP_MAY_RECOVER(stop)
  7460. || zend_jit_trace_exit_is_bad(parent_num, exit_num)) {
  7461. zend_jit_blacklist_trace_exit(parent_num, exit_num);
  7462. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BLACKLIST) {
  7463. fprintf(stderr, "---- EXIT %d/%d blacklisted\n",
  7464. parent_num, exit_num);
  7465. }
  7466. }
  7467. if (ZEND_JIT_TRACE_STOP_REPEAT(stop)) {
  7468. execute_data = EG(current_execute_data);
  7469. return zend_jit_trace_hot_root(execute_data, EX(opline));
  7470. }
  7471. }
  7472. if (JIT_G(debug) & (ZEND_JIT_DEBUG_TRACE_STOP|ZEND_JIT_DEBUG_TRACE_ABORT|ZEND_JIT_DEBUG_TRACE_COMPILED|ZEND_JIT_DEBUG_TRACE_BLACKLIST)) {
  7473. fprintf(stderr, "\n");
  7474. }
  7475. return ret;
  7476. }
  7477. int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs)
  7478. {
  7479. uint32_t trace_num = EG(jit_trace_num);
  7480. zend_execute_data *execute_data = EG(current_execute_data);
  7481. const zend_op *orig_opline = EX(opline);
  7482. const zend_op *opline;
  7483. zend_jit_trace_info *t = &zend_jit_traces[trace_num];
  7484. int repeat_last_opline = 0;
  7485. /* Deoptimizatoion of VM stack state */
  7486. uint32_t i;
  7487. uint32_t stack_size = t->exit_info[exit_num].stack_size;
  7488. zend_jit_trace_stack *stack = t->stack_map + t->exit_info[exit_num].stack_offset;
  7489. if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_RESTORE_CALL) {
  7490. zend_execute_data *call = (zend_execute_data *)regs->gpr[ZREG_RX];
  7491. call->prev_execute_data = EX(call);
  7492. EX(call) = call;
  7493. }
  7494. for (i = 0; i < stack_size; i++) {
  7495. if (STACK_REG(stack, i) != ZREG_NONE) {
  7496. if (STACK_TYPE(stack, i) == IS_LONG) {
  7497. zend_long val;
  7498. if (STACK_REG(stack, i) < ZREG_NUM) {
  7499. val = regs->gpr[STACK_REG(stack, i)];
  7500. } else if (STACK_REG(stack, i) == ZREG_LONG_MIN) {
  7501. val = ZEND_LONG_MIN;
  7502. } else if (STACK_REG(stack, i) == ZREG_LONG_MAX) {
  7503. val = ZEND_LONG_MAX;
  7504. } else {
  7505. ZEND_UNREACHABLE();
  7506. }
  7507. ZVAL_LONG(EX_VAR_NUM(i), val);
  7508. } else if (STACK_TYPE(stack, i) == IS_DOUBLE) {
  7509. double val;
  7510. if (STACK_REG(stack, i) < ZREG_NUM) {
  7511. val = regs->fpr[STACK_REG(stack, i) - ZREG_FIRST_FPR];
  7512. } else if (STACK_REG(stack, i) == ZREG_LONG_MIN_MINUS_1) {
  7513. val = (double)ZEND_LONG_MIN - 1.0;
  7514. } else if (STACK_REG(stack, i) == ZREG_LONG_MAX_PLUS_1) {
  7515. val = (double)ZEND_LONG_MAX + 1.0;
  7516. } else {
  7517. ZEND_UNREACHABLE();
  7518. }
  7519. ZVAL_DOUBLE(EX_VAR_NUM(i), val);
  7520. } else if (STACK_REG(stack, i) == ZREG_THIS) {
  7521. zend_object *obj = Z_OBJ(EX(This));
  7522. GC_ADDREF(obj);
  7523. ZVAL_OBJ(EX_VAR_NUM(i), obj);
  7524. } else if (STACK_REG(stack, i) == ZREG_NULL) {
  7525. ZVAL_NULL(EX_VAR_NUM(i));
  7526. } else if (STACK_REG(stack, i) == ZREG_ZVAL_TRY_ADDREF) {
  7527. Z_TRY_ADDREF_P(EX_VAR_NUM(i));
  7528. } else if (STACK_REG(stack, i) == ZREG_ZVAL_COPY_GPR0) {
  7529. zval *val = (zval*)regs->gpr[ZREG_COPY];
  7530. if (UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF)) {
  7531. /* Undefined array index or property */
  7532. repeat_last_opline = 1;
  7533. } else {
  7534. ZVAL_COPY(EX_VAR_NUM(i), val);
  7535. }
  7536. } else {
  7537. ZEND_UNREACHABLE();
  7538. }
  7539. }
  7540. }
  7541. if (repeat_last_opline) {
  7542. EX(opline) = t->exit_info[exit_num].opline - 1;
  7543. if ((EX(opline)->op1_type & (IS_VAR|IS_TMP_VAR))
  7544. && !(t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1)
  7545. && EX(opline)->opcode != ZEND_FETCH_LIST_R) {
  7546. Z_TRY_ADDREF_P(EX_VAR(EX(opline)->op1.var));
  7547. }
  7548. return 1;
  7549. }
  7550. opline = t->exit_info[exit_num].opline;
  7551. if (opline) {
  7552. if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP2) {
  7553. ZEND_ASSERT((opline-1)->opcode == ZEND_FETCH_DIM_R
  7554. || (opline-1)->opcode == ZEND_FETCH_DIM_IS
  7555. || (opline-1)->opcode == ZEND_FETCH_LIST_R
  7556. || (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG);
  7557. EX(opline) = opline-1;
  7558. zval_ptr_dtor_nogc(EX_VAR((opline-1)->op2.var));
  7559. }
  7560. if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1) {
  7561. ZEND_ASSERT((opline-1)->opcode == ZEND_FETCH_DIM_R
  7562. || (opline-1)->opcode == ZEND_FETCH_DIM_IS
  7563. || (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG
  7564. || (opline-1)->opcode == ZEND_FETCH_OBJ_R
  7565. || (opline-1)->opcode == ZEND_FETCH_OBJ_IS
  7566. || (opline-1)->opcode == ZEND_FETCH_OBJ_FUNC_ARG);
  7567. EX(opline) = opline-1;
  7568. zval_ptr_dtor_nogc(EX_VAR((opline-1)->op1.var));
  7569. }
  7570. if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) {
  7571. if (EG(exception)) {
  7572. return 1;
  7573. }
  7574. }
  7575. if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_METHOD_CALL) {
  7576. zend_function *func = (zend_function*)regs->gpr[ZREG_COPY];
  7577. if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
  7578. zend_string_release_ex(func->common.function_name, 0);
  7579. zend_free_trampoline(func);
  7580. EX(opline) = opline;
  7581. return 1;
  7582. }
  7583. }
  7584. /* Set VM opline to continue interpretation */
  7585. EX(opline) = opline;
  7586. }
  7587. if (EG(vm_interrupt) || JIT_G(tracing)) {
  7588. return 1;
  7589. /* Lock-free check if the side trace was already JIT-ed or blacklist-ed in another process */
  7590. } else if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED)) {
  7591. return 0;
  7592. }
  7593. ZEND_ASSERT(EX(func)->type == ZEND_USER_FUNCTION);
  7594. ZEND_ASSERT(EX(opline) >= EX(func)->op_array.opcodes &&
  7595. EX(opline) < EX(func)->op_array.opcodes + EX(func)->op_array.last);
  7596. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_EXIT) {
  7597. fprintf(stderr, " TRACE %d exit %d %s%s%s() %s:%d\n",
  7598. trace_num,
  7599. exit_num,
  7600. EX(func)->op_array.scope ? ZSTR_VAL(EX(func)->op_array.scope->name) : "",
  7601. EX(func)->op_array.scope ? "::" : "",
  7602. EX(func)->op_array.function_name ?
  7603. ZSTR_VAL(EX(func)->op_array.function_name) : "$main",
  7604. ZSTR_VAL(EX(func)->op_array.filename),
  7605. EX(opline)->lineno);
  7606. }
  7607. if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_INVALIDATE) {
  7608. zend_jit_op_array_trace_extension *jit_extension;
  7609. uint32_t num = trace_num;
  7610. while (t->root != num) {
  7611. num = t->root;
  7612. t = &zend_jit_traces[num];
  7613. }
  7614. SHM_UNPROTECT();
  7615. zend_jit_unprotect();
  7616. jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(t->op_array);
  7617. if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_LOOP) {
  7618. ((zend_op*)(t->opline))->handler = (const void*)zend_jit_loop_trace_counter_handler;
  7619. } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_ENTER) {
  7620. ((zend_op*)(t->opline))->handler = (const void*)zend_jit_func_trace_counter_handler;
  7621. } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_RETURN) {
  7622. ((zend_op*)(t->opline))->handler = (const void*)zend_jit_ret_trace_counter_handler;
  7623. }
  7624. ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &=
  7625. ZEND_JIT_TRACE_START_LOOP|ZEND_JIT_TRACE_START_ENTER|ZEND_JIT_TRACE_START_RETURN;
  7626. zend_jit_protect();
  7627. SHM_PROTECT();
  7628. return 0;
  7629. }
  7630. if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_TO_VM) {
  7631. if (zend_jit_trace_exit_is_bad(trace_num, exit_num)) {
  7632. zend_jit_blacklist_trace_exit(trace_num, exit_num);
  7633. if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BLACKLIST) {
  7634. fprintf(stderr, "---- EXIT %d/%d blacklisted\n",
  7635. trace_num, exit_num);
  7636. }
  7637. return 0;
  7638. }
  7639. } else if (JIT_G(hot_side_exit) && zend_jit_trace_exit_is_hot(trace_num, exit_num)) {
  7640. return zend_jit_trace_hot_side(execute_data, trace_num, exit_num);
  7641. }
  7642. /* Return 1 to call original handler instead of the same JIT-ed trace */
  7643. return (orig_opline == t->opline && EX(opline) == orig_opline);
  7644. }
  7645. static zend_always_inline uint8_t zend_jit_trace_supported(const zend_op *opline)
  7646. {
  7647. switch (opline->opcode) {
  7648. case ZEND_CATCH:
  7649. case ZEND_FAST_CALL:
  7650. case ZEND_FAST_RET:
  7651. return ZEND_JIT_TRACE_UNSUPPORTED;
  7652. default:
  7653. return ZEND_JIT_TRACE_SUPPORTED;
  7654. }
  7655. }
  7656. static int zend_jit_restart_hot_trace_counters(zend_op_array *op_array)
  7657. {
  7658. zend_jit_op_array_trace_extension *jit_extension;
  7659. uint32_t i;
  7660. jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
  7661. for (i = 0; i < op_array->last; i++) {
  7662. jit_extension->trace_info[i].trace_flags &=
  7663. ZEND_JIT_TRACE_START_LOOP | ZEND_JIT_TRACE_START_ENTER | ZEND_JIT_TRACE_UNSUPPORTED;
  7664. if (jit_extension->trace_info[i].trace_flags == ZEND_JIT_TRACE_START_LOOP) {
  7665. op_array->opcodes[i].handler = (const void*)zend_jit_loop_trace_counter_handler;
  7666. } else if (jit_extension->trace_info[i].trace_flags == ZEND_JIT_TRACE_START_ENTER) {
  7667. op_array->opcodes[i].handler = (const void*)zend_jit_func_trace_counter_handler;
  7668. } else {
  7669. op_array->opcodes[i].handler = jit_extension->trace_info[i].orig_handler;
  7670. }
  7671. }
  7672. return SUCCESS;
  7673. }
  7674. static int zend_jit_setup_hot_trace_counters(zend_op_array *op_array)
  7675. {
  7676. zend_op *opline;
  7677. zend_jit_op_array_trace_extension *jit_extension;
  7678. uint32_t i;
  7679. ZEND_ASSERT(sizeof(zend_op_trace_info) == sizeof(zend_op));
  7680. jit_extension = (zend_jit_op_array_trace_extension*)zend_shared_alloc(sizeof(zend_jit_op_array_trace_extension) + (op_array->last - 1) * sizeof(zend_op_trace_info));
  7681. if (!jit_extension) {
  7682. return FAILURE;
  7683. }
  7684. memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
  7685. jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_HOT_TRACE;
  7686. jit_extension->op_array = op_array;
  7687. jit_extension->offset = (char*)jit_extension->trace_info - (char*)op_array->opcodes;
  7688. for (i = 0; i < op_array->last; i++) {
  7689. jit_extension->trace_info[i].orig_handler = op_array->opcodes[i].handler;
  7690. jit_extension->trace_info[i].call_handler = zend_get_opcode_handler_func(&op_array->opcodes[i]);
  7691. jit_extension->trace_info[i].counter = NULL;
  7692. jit_extension->trace_info[i].trace_flags =
  7693. zend_jit_trace_supported(&op_array->opcodes[i]);
  7694. }
  7695. ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
  7696. if (JIT_G(hot_loop)) {
  7697. zend_cfg cfg;
  7698. ZEND_ASSERT(zend_jit_loop_trace_counter_handler != NULL);
  7699. if (zend_jit_build_cfg(op_array, &cfg) != SUCCESS) {
  7700. return FAILURE;
  7701. }
  7702. for (i = 0; i < cfg.blocks_count; i++) {
  7703. if (cfg.blocks[i].flags & ZEND_BB_REACHABLE) {
  7704. if (cfg.blocks[i].flags & ZEND_BB_LOOP_HEADER) {
  7705. /* loop header */
  7706. opline = op_array->opcodes + cfg.blocks[i].start;
  7707. if (!(ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_UNSUPPORTED)) {
  7708. opline->handler = (const void*)zend_jit_loop_trace_counter_handler;
  7709. if (!ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->counter) {
  7710. ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->counter =
  7711. &zend_jit_hot_counters[ZEND_JIT_COUNTER_NUM];
  7712. ZEND_JIT_COUNTER_NUM = (ZEND_JIT_COUNTER_NUM + 1) % ZEND_HOT_COUNTERS_COUNT;
  7713. }
  7714. ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->trace_flags |=
  7715. ZEND_JIT_TRACE_START_LOOP;
  7716. }
  7717. }
  7718. }
  7719. }
  7720. }
  7721. if (JIT_G(hot_func)) {
  7722. ZEND_ASSERT(zend_jit_func_trace_counter_handler != NULL);
  7723. opline = op_array->opcodes;
  7724. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  7725. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  7726. opline++;
  7727. }
  7728. }
  7729. if (!ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->trace_flags) {
  7730. /* function entry */
  7731. opline->handler = (const void*)zend_jit_func_trace_counter_handler;
  7732. ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->counter =
  7733. &zend_jit_hot_counters[ZEND_JIT_COUNTER_NUM];
  7734. ZEND_JIT_COUNTER_NUM = (ZEND_JIT_COUNTER_NUM + 1) % ZEND_HOT_COUNTERS_COUNT;
  7735. ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->trace_flags |=
  7736. ZEND_JIT_TRACE_START_ENTER;
  7737. }
  7738. }
  7739. zend_shared_alloc_register_xlat_entry(op_array->opcodes, jit_extension);
  7740. return SUCCESS;
  7741. }
  7742. static void zend_jit_trace_init_caches(void)
  7743. {
  7744. memset(ZEND_VOIDP(JIT_G(bad_root_cache_opline)), 0, sizeof(JIT_G(bad_root_cache_opline)));
  7745. memset(JIT_G(bad_root_cache_count), 0, sizeof(JIT_G(bad_root_cache_count)));
  7746. memset(JIT_G(bad_root_cache_stop), 0, sizeof(JIT_G(bad_root_cache_count)));
  7747. JIT_G(bad_root_slot) = 0;
  7748. if (JIT_G(exit_counters)) {
  7749. memset(JIT_G(exit_counters), 0, JIT_G(max_exit_counters));
  7750. }
  7751. }
  7752. static void zend_jit_trace_reset_caches(void)
  7753. {
  7754. JIT_G(tracing) = 0;
  7755. #ifdef ZTS
  7756. if (!JIT_G(exit_counters)) {
  7757. JIT_G(exit_counters) = calloc(JIT_G(max_exit_counters), 1);
  7758. }
  7759. #endif
  7760. }
  7761. static void zend_jit_trace_restart(void)
  7762. {
  7763. ZEND_JIT_TRACE_NUM = 1;
  7764. ZEND_JIT_COUNTER_NUM = 0;
  7765. ZEND_JIT_EXIT_NUM = 0;
  7766. ZEND_JIT_EXIT_COUNTERS = 0;
  7767. zend_jit_trace_init_caches();
  7768. }