zend_jit.c 148 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209
  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. #include "main/php.h"
  19. #include "main/SAPI.h"
  20. #include "php_version.h"
  21. #include <ZendAccelerator.h>
  22. #include "zend_shared_alloc.h"
  23. #include "Zend/zend_execute.h"
  24. #include "Zend/zend_vm.h"
  25. #include "Zend/zend_exceptions.h"
  26. #include "Zend/zend_constants.h"
  27. #include "Zend/zend_closures.h"
  28. #include "Zend/zend_ini.h"
  29. #include "Zend/zend_observer.h"
  30. #include "zend_smart_str.h"
  31. #include "jit/zend_jit.h"
  32. #ifdef HAVE_JIT
  33. #include "Optimizer/zend_func_info.h"
  34. #include "Optimizer/zend_ssa.h"
  35. #include "Optimizer/zend_inference.h"
  36. #include "Optimizer/zend_call_graph.h"
  37. #include "Optimizer/zend_dump.h"
  38. #if ZEND_JIT_TARGET_X86
  39. # include "jit/zend_jit_x86.h"
  40. #elif ZEND_JIT_TARGET_ARM64
  41. # include "jit/zend_jit_arm64.h"
  42. #endif
  43. #include "jit/zend_jit_internal.h"
  44. #ifdef ZTS
  45. int jit_globals_id;
  46. #else
  47. zend_jit_globals jit_globals;
  48. #endif
  49. //#define CONTEXT_THREADED_JIT
  50. #define ZEND_JIT_USE_RC_INFERENCE
  51. #ifdef ZEND_JIT_USE_RC_INFERENCE
  52. # define ZEND_SSA_RC_INFERENCE_FLAG ZEND_SSA_RC_INFERENCE
  53. # define RC_MAY_BE_1(info) (((info) & (MAY_BE_RC1|MAY_BE_REF)) != 0)
  54. # define RC_MAY_BE_N(info) (((info) & (MAY_BE_RCN|MAY_BE_REF)) != 0)
  55. #else
  56. # define ZEND_SSA_RC_INFERENCE_FLAG 0
  57. # define RC_MAY_BE_1(info) 1
  58. # define RC_MAY_BE_N(info) 1
  59. #endif
  60. #define JIT_PREFIX "JIT$"
  61. #define JIT_STUB_PREFIX "JIT$$"
  62. #define TRACE_PREFIX "TRACE-"
  63. #define DASM_M_GROW(ctx, t, p, sz, need) \
  64. do { \
  65. size_t _sz = (sz), _need = (need); \
  66. if (_sz < _need) { \
  67. if (_sz < 16) _sz = 16; \
  68. while (_sz < _need) _sz += _sz; \
  69. (p) = (t *)erealloc((p), _sz); \
  70. (sz) = _sz; \
  71. } \
  72. } while(0)
  73. #define DASM_M_FREE(ctx, p, sz) efree(p)
  74. #if ZEND_DEBUG
  75. # define DASM_CHECKS 1
  76. #endif
  77. #include "dynasm/dasm_proto.h"
  78. typedef struct _zend_jit_stub {
  79. const char *name;
  80. int (*stub)(dasm_State **Dst);
  81. uint32_t offset;
  82. uint32_t adjustment;
  83. } zend_jit_stub;
  84. #define JIT_STUB(name, offset, adjustment) \
  85. {JIT_STUB_PREFIX #name, zend_jit_ ## name ## _stub, offset, adjustment}
  86. zend_ulong zend_jit_profile_counter = 0;
  87. int zend_jit_profile_counter_rid = -1;
  88. int16_t zend_jit_hot_counters[ZEND_HOT_COUNTERS_COUNT];
  89. const zend_op *zend_jit_halt_op = NULL;
  90. static int zend_jit_vm_kind = 0;
  91. static void *dasm_buf = NULL;
  92. static void *dasm_end = NULL;
  93. static void **dasm_ptr = NULL;
  94. static size_t dasm_size = 0;
  95. static zend_long jit_bisect_pos = 0;
  96. static const void *zend_jit_runtime_jit_handler = NULL;
  97. static const void *zend_jit_profile_jit_handler = NULL;
  98. static const void *zend_jit_func_hot_counter_handler = NULL;
  99. static const void *zend_jit_loop_hot_counter_handler = NULL;
  100. static const void *zend_jit_func_trace_counter_handler = NULL;
  101. static const void *zend_jit_ret_trace_counter_handler = NULL;
  102. static const void *zend_jit_loop_trace_counter_handler = NULL;
  103. static int ZEND_FASTCALL zend_runtime_jit(void);
  104. static int zend_jit_trace_op_len(const zend_op *opline);
  105. static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op *opline);
  106. static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t flags);
  107. static const void *zend_jit_trace_get_exit_addr(uint32_t n);
  108. static void zend_jit_trace_add_code(const void *start, uint32_t size);
  109. static bool zend_jit_needs_arg_dtor(const zend_function *func, uint32_t arg_num, zend_call_info *call_info);
  110. #if ZEND_JIT_TARGET_ARM64
  111. static zend_jit_trace_info *zend_jit_get_current_trace_info(void);
  112. static uint32_t zend_jit_trace_find_exit_point(const void* addr);
  113. #endif
  114. static int zend_jit_assign_to_variable(dasm_State **Dst,
  115. const zend_op *opline,
  116. zend_jit_addr var_use_addr,
  117. zend_jit_addr var_addr,
  118. uint32_t var_info,
  119. uint32_t var_def_info,
  120. zend_uchar val_type,
  121. zend_jit_addr val_addr,
  122. uint32_t val_info,
  123. zend_jit_addr res_addr,
  124. bool check_exception);
  125. static bool dominates(const zend_basic_block *blocks, int a, int b) {
  126. while (blocks[b].level > blocks[a].level) {
  127. b = blocks[b].idom;
  128. }
  129. return a == b;
  130. }
  131. static bool zend_ssa_is_last_use(const zend_op_array *op_array, const zend_ssa *ssa, int var, int use)
  132. {
  133. int next_use;
  134. if (ssa->vars[var].phi_use_chain) {
  135. zend_ssa_phi *phi = ssa->vars[var].phi_use_chain;
  136. do {
  137. if (!ssa->vars[phi->ssa_var].no_val) {
  138. return 0;
  139. }
  140. phi = zend_ssa_next_use_phi(ssa, var, phi);
  141. } while (phi);
  142. }
  143. if (ssa->cfg.blocks[ssa->cfg.map[use]].loop_header > 0
  144. || (ssa->cfg.blocks[ssa->cfg.map[use]].flags & ZEND_BB_LOOP_HEADER)) {
  145. int b = ssa->cfg.map[use];
  146. int prev_use = ssa->vars[var].use_chain;
  147. while (prev_use >= 0 && prev_use != use) {
  148. if (b != ssa->cfg.map[prev_use]
  149. && dominates(ssa->cfg.blocks, b, ssa->cfg.map[prev_use])
  150. && !zend_ssa_is_no_val_use(op_array->opcodes + prev_use, ssa->ops + prev_use, var)) {
  151. return 0;
  152. }
  153. prev_use = zend_ssa_next_use(ssa->ops, var, prev_use);
  154. }
  155. }
  156. next_use = zend_ssa_next_use(ssa->ops, var, use);
  157. if (next_use < 0) {
  158. return 1;
  159. } else if (zend_ssa_is_no_val_use(op_array->opcodes + next_use, ssa->ops + next_use, var)) {
  160. return 1;
  161. }
  162. return 0;
  163. }
  164. static bool zend_ival_is_last_use(const zend_lifetime_interval *ival, int use)
  165. {
  166. if (ival->flags & ZREG_LAST_USE) {
  167. const zend_life_range *range = &ival->range;
  168. while (range->next) {
  169. range = range->next;
  170. }
  171. return range->end == use;
  172. }
  173. return 0;
  174. }
  175. static bool zend_is_commutative(zend_uchar opcode)
  176. {
  177. return
  178. opcode == ZEND_ADD ||
  179. opcode == ZEND_MUL ||
  180. opcode == ZEND_BW_OR ||
  181. opcode == ZEND_BW_AND ||
  182. opcode == ZEND_BW_XOR;
  183. }
  184. static int zend_jit_is_constant_cmp_long_long(const zend_op *opline,
  185. zend_ssa_range *op1_range,
  186. zend_jit_addr op1_addr,
  187. zend_ssa_range *op2_range,
  188. zend_jit_addr op2_addr,
  189. bool *result)
  190. {
  191. zend_long op1_min;
  192. zend_long op1_max;
  193. zend_long op2_min;
  194. zend_long op2_max;
  195. if (op1_range) {
  196. op1_min = op1_range->min;
  197. op1_max = op1_range->max;
  198. } else if (Z_MODE(op1_addr) == IS_CONST_ZVAL) {
  199. ZEND_ASSERT(Z_TYPE_P(Z_ZV(op1_addr)) == IS_LONG);
  200. op1_min = op1_max = Z_LVAL_P(Z_ZV(op1_addr));
  201. } else {
  202. return 0;
  203. }
  204. if (op2_range) {
  205. op2_min = op2_range->min;
  206. op2_max = op2_range->max;
  207. } else if (Z_MODE(op2_addr) == IS_CONST_ZVAL) {
  208. ZEND_ASSERT(Z_TYPE_P(Z_ZV(op2_addr)) == IS_LONG);
  209. op2_min = op2_max = Z_LVAL_P(Z_ZV(op2_addr));
  210. } else {
  211. return 0;
  212. }
  213. switch (opline->opcode) {
  214. case ZEND_IS_EQUAL:
  215. case ZEND_IS_IDENTICAL:
  216. case ZEND_CASE:
  217. case ZEND_CASE_STRICT:
  218. if (op1_min == op1_max && op2_min == op2_max && op1_min == op2_min) {
  219. *result = 1;
  220. return 1;
  221. } else if (op1_max < op2_min || op1_min > op2_max) {
  222. *result = 0;
  223. return 1;
  224. }
  225. return 0;
  226. case ZEND_IS_NOT_EQUAL:
  227. case ZEND_IS_NOT_IDENTICAL:
  228. if (op1_min == op1_max && op2_min == op2_max && op1_min == op2_min) {
  229. *result = 0;
  230. return 1;
  231. } else if (op1_max < op2_min || op1_min > op2_max) {
  232. *result = 1;
  233. return 1;
  234. }
  235. return 0;
  236. case ZEND_IS_SMALLER:
  237. if (op1_max < op2_min) {
  238. *result = 1;
  239. return 1;
  240. } else if (op1_min >= op2_max) {
  241. *result = 0;
  242. return 1;
  243. }
  244. return 0;
  245. case ZEND_IS_SMALLER_OR_EQUAL:
  246. if (op1_max <= op2_min) {
  247. *result = 1;
  248. return 1;
  249. } else if (op1_min > op2_max) {
  250. *result = 0;
  251. return 1;
  252. }
  253. return 0;
  254. default:
  255. ZEND_UNREACHABLE();
  256. }
  257. return 0;
  258. }
  259. static int zend_jit_needs_call_chain(zend_call_info *call_info, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, const zend_op *opline, int call_level, zend_jit_trace_rec *trace)
  260. {
  261. int skip;
  262. if (trace) {
  263. zend_jit_trace_rec *p = trace;
  264. ssa_op++;
  265. while (1) {
  266. if (p->op == ZEND_JIT_TRACE_VM) {
  267. switch (p->opline->opcode) {
  268. case ZEND_SEND_ARRAY:
  269. case ZEND_SEND_USER:
  270. case ZEND_SEND_UNPACK:
  271. case ZEND_INIT_FCALL:
  272. case ZEND_INIT_METHOD_CALL:
  273. case ZEND_INIT_STATIC_METHOD_CALL:
  274. case ZEND_INIT_FCALL_BY_NAME:
  275. case ZEND_INIT_NS_FCALL_BY_NAME:
  276. case ZEND_INIT_DYNAMIC_CALL:
  277. case ZEND_NEW:
  278. case ZEND_INIT_USER_CALL:
  279. case ZEND_FAST_CALL:
  280. case ZEND_JMP:
  281. case ZEND_JMPZNZ:
  282. case ZEND_JMPZ:
  283. case ZEND_JMPNZ:
  284. case ZEND_JMPZ_EX:
  285. case ZEND_JMPNZ_EX:
  286. case ZEND_FE_RESET_R:
  287. case ZEND_FE_RESET_RW:
  288. case ZEND_JMP_SET:
  289. case ZEND_COALESCE:
  290. case ZEND_JMP_NULL:
  291. case ZEND_ASSERT_CHECK:
  292. case ZEND_CATCH:
  293. case ZEND_DECLARE_ANON_CLASS:
  294. case ZEND_FE_FETCH_R:
  295. case ZEND_FE_FETCH_RW:
  296. return 1;
  297. case ZEND_DO_ICALL:
  298. case ZEND_DO_UCALL:
  299. case ZEND_DO_FCALL_BY_NAME:
  300. case ZEND_DO_FCALL:
  301. case ZEND_CALLABLE_CONVERT:
  302. return 0;
  303. case ZEND_SEND_VAL:
  304. case ZEND_SEND_VAR:
  305. case ZEND_SEND_VAL_EX:
  306. case ZEND_SEND_VAR_EX:
  307. case ZEND_SEND_FUNC_ARG:
  308. case ZEND_SEND_REF:
  309. case ZEND_SEND_VAR_NO_REF:
  310. case ZEND_SEND_VAR_NO_REF_EX:
  311. /* skip */
  312. break;
  313. default:
  314. if (zend_may_throw(opline, ssa_op, op_array, ssa)) {
  315. return 1;
  316. }
  317. }
  318. ssa_op += zend_jit_trace_op_len(opline);
  319. } else if (p->op == ZEND_JIT_TRACE_ENTER ||
  320. p->op == ZEND_JIT_TRACE_BACK ||
  321. p->op == ZEND_JIT_TRACE_END) {
  322. return 1;
  323. }
  324. p++;
  325. }
  326. }
  327. if (!call_info) {
  328. const zend_op *end = op_array->opcodes + op_array->last;
  329. opline++;
  330. ssa_op++;
  331. skip = (call_level == 1);
  332. while (opline != end) {
  333. if (!skip) {
  334. if (zend_may_throw(opline, ssa_op, op_array, ssa)) {
  335. return 1;
  336. }
  337. }
  338. switch (opline->opcode) {
  339. case ZEND_SEND_VAL:
  340. case ZEND_SEND_VAR:
  341. case ZEND_SEND_VAL_EX:
  342. case ZEND_SEND_VAR_EX:
  343. case ZEND_SEND_FUNC_ARG:
  344. case ZEND_SEND_REF:
  345. case ZEND_SEND_VAR_NO_REF:
  346. case ZEND_SEND_VAR_NO_REF_EX:
  347. skip = 0;
  348. break;
  349. case ZEND_SEND_ARRAY:
  350. case ZEND_SEND_USER:
  351. case ZEND_SEND_UNPACK:
  352. case ZEND_INIT_FCALL:
  353. case ZEND_INIT_METHOD_CALL:
  354. case ZEND_INIT_STATIC_METHOD_CALL:
  355. case ZEND_INIT_FCALL_BY_NAME:
  356. case ZEND_INIT_NS_FCALL_BY_NAME:
  357. case ZEND_INIT_DYNAMIC_CALL:
  358. case ZEND_NEW:
  359. case ZEND_INIT_USER_CALL:
  360. case ZEND_FAST_CALL:
  361. case ZEND_JMP:
  362. case ZEND_JMPZNZ:
  363. case ZEND_JMPZ:
  364. case ZEND_JMPNZ:
  365. case ZEND_JMPZ_EX:
  366. case ZEND_JMPNZ_EX:
  367. case ZEND_FE_RESET_R:
  368. case ZEND_FE_RESET_RW:
  369. case ZEND_JMP_SET:
  370. case ZEND_COALESCE:
  371. case ZEND_JMP_NULL:
  372. case ZEND_ASSERT_CHECK:
  373. case ZEND_CATCH:
  374. case ZEND_DECLARE_ANON_CLASS:
  375. case ZEND_FE_FETCH_R:
  376. case ZEND_FE_FETCH_RW:
  377. return 1;
  378. case ZEND_DO_ICALL:
  379. case ZEND_DO_UCALL:
  380. case ZEND_DO_FCALL_BY_NAME:
  381. case ZEND_DO_FCALL:
  382. case ZEND_CALLABLE_CONVERT:
  383. end = opline;
  384. if (end - op_array->opcodes >= ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len) {
  385. /* INIT_FCALL and DO_FCALL in different BasicBlocks */
  386. return 1;
  387. }
  388. return 0;
  389. }
  390. opline++;
  391. ssa_op++;
  392. }
  393. return 1;
  394. } else {
  395. const zend_op *end = call_info->caller_call_opline;
  396. /* end may be null if an opcode like EXIT is part of the argument list. */
  397. if (!end || end - op_array->opcodes >= ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len) {
  398. /* INIT_FCALL and DO_FCALL in different BasicBlocks */
  399. return 1;
  400. }
  401. opline++;
  402. ssa_op++;
  403. skip = (call_level == 1);
  404. while (opline != end) {
  405. if (skip) {
  406. switch (opline->opcode) {
  407. case ZEND_SEND_VAL:
  408. case ZEND_SEND_VAR:
  409. case ZEND_SEND_VAL_EX:
  410. case ZEND_SEND_VAR_EX:
  411. case ZEND_SEND_FUNC_ARG:
  412. case ZEND_SEND_REF:
  413. case ZEND_SEND_VAR_NO_REF:
  414. case ZEND_SEND_VAR_NO_REF_EX:
  415. skip = 0;
  416. break;
  417. case ZEND_SEND_ARRAY:
  418. case ZEND_SEND_USER:
  419. case ZEND_SEND_UNPACK:
  420. return 1;
  421. }
  422. } else {
  423. if (zend_may_throw(opline, ssa_op, op_array, ssa)) {
  424. return 1;
  425. }
  426. }
  427. opline++;
  428. ssa_op++;
  429. }
  430. return 0;
  431. }
  432. }
  433. static uint32_t skip_valid_arguments(const zend_op_array *op_array, zend_ssa *ssa, const zend_call_info *call_info)
  434. {
  435. uint32_t num_args = 0;
  436. zend_function *func = call_info->callee_func;
  437. /* It's okay to handle prototypes here, because they can only increase the accepted arguments.
  438. * Anything legal for the parent method is also legal for the parent method. */
  439. while (num_args < call_info->num_args) {
  440. zend_arg_info *arg_info = func->op_array.arg_info + num_args;
  441. if (ZEND_TYPE_IS_SET(arg_info->type)) {
  442. if (ZEND_TYPE_IS_ONLY_MASK(arg_info->type)) {
  443. zend_op *opline = call_info->arg_info[num_args].opline;
  444. zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
  445. uint32_t type_mask = ZEND_TYPE_PURE_MASK(arg_info->type);
  446. if ((OP1_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF)) & ~type_mask) {
  447. break;
  448. }
  449. } else {
  450. break;
  451. }
  452. }
  453. num_args++;
  454. }
  455. return num_args;
  456. }
  457. static uint32_t zend_ssa_cv_info(const zend_op_array *op_array, zend_ssa *ssa, uint32_t var)
  458. {
  459. uint32_t j, info;
  460. if (ssa->vars && ssa->var_info) {
  461. info = ssa->var_info[var].type;
  462. for (j = op_array->last_var; j < ssa->vars_count; j++) {
  463. if (ssa->vars[j].var == var) {
  464. info |= ssa->var_info[j].type;
  465. }
  466. }
  467. } else {
  468. info = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_UNDEF |
  469. MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  470. }
  471. #ifdef ZEND_JIT_USE_RC_INFERENCE
  472. /* Refcount may be increased by RETURN opcode */
  473. if ((info & MAY_BE_RC1) && !(info & MAY_BE_RCN)) {
  474. for (j = 0; j < ssa->cfg.blocks_count; j++) {
  475. if ((ssa->cfg.blocks[j].flags & ZEND_BB_REACHABLE) &&
  476. ssa->cfg.blocks[j].len > 0) {
  477. const zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].start + ssa->cfg.blocks[j].len - 1;
  478. if (opline->opcode == ZEND_RETURN) {
  479. if (opline->op1_type == IS_CV && opline->op1.var == EX_NUM_TO_VAR(var)) {
  480. info |= MAY_BE_RCN;
  481. break;
  482. }
  483. }
  484. }
  485. }
  486. }
  487. #endif
  488. return info;
  489. }
  490. static bool zend_jit_may_avoid_refcounting(const zend_op *opline, uint32_t op1_info)
  491. {
  492. switch (opline->opcode) {
  493. case ZEND_FETCH_OBJ_FUNC_ARG:
  494. if (!JIT_G(current_frame) ||
  495. !JIT_G(current_frame)->call->func ||
  496. !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
  497. return 0;
  498. }
  499. /* break missing intentionally */
  500. case ZEND_FETCH_OBJ_R:
  501. case ZEND_FETCH_OBJ_IS:
  502. if ((op1_info & MAY_BE_OBJECT)
  503. && opline->op2_type == IS_CONST
  504. && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_STRING
  505. && Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] != '\0') {
  506. return 1;
  507. }
  508. break;
  509. case ZEND_FETCH_DIM_FUNC_ARG:
  510. if (!JIT_G(current_frame) ||
  511. !JIT_G(current_frame)->call->func ||
  512. !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
  513. return 0;
  514. }
  515. /* break missing intentionally */
  516. case ZEND_FETCH_DIM_R:
  517. case ZEND_FETCH_DIM_IS:
  518. return 1;
  519. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  520. if (!(opline->extended_value & ZEND_ISEMPTY)) {
  521. return 1;
  522. }
  523. break;
  524. }
  525. return 0;
  526. }
  527. static bool zend_jit_is_persistent_constant(zval *key, uint32_t flags)
  528. {
  529. zval *zv;
  530. zend_constant *c = NULL;
  531. /* null/true/false are resolved during compilation, so don't check for them here. */
  532. zv = zend_hash_find_known_hash(EG(zend_constants), Z_STR_P(key));
  533. if (zv) {
  534. c = (zend_constant*)Z_PTR_P(zv);
  535. } else if (flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE) {
  536. key++;
  537. zv = zend_hash_find_known_hash(EG(zend_constants), Z_STR_P(key));
  538. if (zv) {
  539. c = (zend_constant*)Z_PTR_P(zv);
  540. }
  541. }
  542. return c && (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
  543. }
  544. static zend_property_info* zend_get_known_property_info(const zend_op_array *op_array, zend_class_entry *ce, zend_string *member, bool on_this, zend_string *filename)
  545. {
  546. zend_property_info *info = NULL;
  547. if ((on_this && (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) ||
  548. !ce ||
  549. !(ce->ce_flags & ZEND_ACC_LINKED) ||
  550. (ce->ce_flags & ZEND_ACC_TRAIT) ||
  551. ce->create_object) {
  552. return NULL;
  553. }
  554. if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
  555. if (ce->info.user.filename != filename) {
  556. /* class declaration might be changed independently */
  557. return NULL;
  558. }
  559. if (ce->parent) {
  560. zend_class_entry *parent = ce->parent;
  561. do {
  562. if (parent->type == ZEND_INTERNAL_CLASS) {
  563. break;
  564. } else if (parent->info.user.filename != filename) {
  565. /* some of parents class declarations might be changed independently */
  566. /* TODO: this check may be not enough, because even
  567. * in the same it's possible to conditionally define
  568. * few classes with the same name, and "parent" may
  569. * change from request to request.
  570. */
  571. return NULL;
  572. }
  573. parent = parent->parent;
  574. } while (parent);
  575. }
  576. }
  577. info = (zend_property_info*)zend_hash_find_ptr(&ce->properties_info, member);
  578. if (info == NULL ||
  579. !IS_VALID_PROPERTY_OFFSET(info->offset) ||
  580. (info->flags & ZEND_ACC_STATIC)) {
  581. return NULL;
  582. }
  583. if (info->flags & ZEND_ACC_PUBLIC) {
  584. return info;
  585. } else if (on_this) {
  586. if (ce == info->ce) {
  587. return info;
  588. } else if ((info->flags & ZEND_ACC_PROTECTED)
  589. && instanceof_function_slow(ce, info->ce)) {
  590. return info;
  591. }
  592. }
  593. return NULL;
  594. }
  595. static bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string *member, bool on_this, zend_string *filename)
  596. {
  597. zend_property_info *info;
  598. if (!ce || (ce->ce_flags & ZEND_ACC_TRAIT)) {
  599. return 1;
  600. }
  601. if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
  602. if (ce->info.user.filename != filename) {
  603. /* class declaration might be changed independently */
  604. return 1;
  605. }
  606. }
  607. info = (zend_property_info*)zend_hash_find_ptr(&ce->properties_info, member);
  608. if (info == NULL ||
  609. !IS_VALID_PROPERTY_OFFSET(info->offset) ||
  610. (info->flags & ZEND_ACC_STATIC)) {
  611. return 1;
  612. }
  613. if (!(info->flags & ZEND_ACC_PUBLIC) &&
  614. (!on_this || info->ce != ce)) {
  615. return 1;
  616. }
  617. return 0;
  618. }
  619. #define OP_RANGE(ssa_op, opN) \
  620. (((opline->opN##_type & (IS_TMP_VAR|IS_VAR|IS_CV)) && \
  621. ssa->var_info && \
  622. (ssa_op)->opN##_use >= 0 && \
  623. ssa->var_info[(ssa_op)->opN##_use].has_range) ? \
  624. &ssa->var_info[(ssa_op)->opN##_use].range : NULL)
  625. #define OP1_RANGE() OP_RANGE(ssa_op, op1)
  626. #define OP2_RANGE() OP_RANGE(ssa_op, op2)
  627. #define OP1_DATA_RANGE() OP_RANGE(ssa_op + 1, op1)
  628. #if ZEND_JIT_TARGET_X86
  629. # include "dynasm/dasm_x86.h"
  630. #elif ZEND_JIT_TARGET_ARM64
  631. static int zend_jit_add_veneer(dasm_State *Dst, void *buffer, uint32_t ins, int *b, uint32_t *cp, ptrdiff_t offset);
  632. # define DASM_ADD_VENEER zend_jit_add_veneer
  633. # include "dynasm/dasm_arm64.h"
  634. #endif
  635. #include "jit/zend_jit_helpers.c"
  636. #include "jit/zend_jit_disasm.c"
  637. #ifndef _WIN32
  638. # include "jit/zend_jit_gdb.h"
  639. # include "jit/zend_jit_perf_dump.c"
  640. #endif
  641. #ifdef HAVE_OPROFILE
  642. # include "jit/zend_jit_oprofile.c"
  643. #endif
  644. #include "Zend/zend_cpuinfo.h"
  645. #ifdef HAVE_VALGRIND
  646. # include <valgrind/valgrind.h>
  647. #endif
  648. #ifdef HAVE_GCC_GLOBAL_REGS
  649. # define GCC_GLOBAL_REGS 1
  650. #else
  651. # define GCC_GLOBAL_REGS 0
  652. #endif
  653. /* By default avoid JITing inline handlers if it does not seem profitable due to lack of
  654. * type information. Disabling this option allows testing some JIT handlers in the
  655. * presence of try/catch blocks, which prevent SSA construction. */
  656. #ifndef PROFITABILITY_CHECKS
  657. # define PROFITABILITY_CHECKS 1
  658. #endif
  659. #define BP_JIT_IS 6 /* Used for ISSET_ISEMPTY_DIM_OBJ. see BP_VAR_*defines in Zend/zend_compile.h */
  660. typedef enum _sp_adj_kind {
  661. SP_ADJ_NONE,
  662. SP_ADJ_RET,
  663. SP_ADJ_VM,
  664. SP_ADJ_JIT,
  665. SP_ADJ_ASSIGN,
  666. SP_ADJ_LAST
  667. } sp_adj_kind;
  668. static int sp_adj[SP_ADJ_LAST];
  669. /* The generated code may contain tautological comparisons, ignore them. */
  670. #if defined(__clang__)
  671. # pragma clang diagnostic push
  672. # pragma clang diagnostic ignored "-Wtautological-compare"
  673. # pragma clang diagnostic ignored "-Wstring-compare"
  674. #endif
  675. #if ZEND_JIT_TARGET_X86
  676. # include "jit/zend_jit_vtune.c"
  677. # include "jit/zend_jit_x86.c"
  678. #elif ZEND_JIT_TARGET_ARM64
  679. # include "jit/zend_jit_arm64.c"
  680. #endif
  681. #if defined(__clang__)
  682. # pragma clang diagnostic pop
  683. #endif
  684. #if _WIN32
  685. # include <Windows.h>
  686. #else
  687. # include <sys/mman.h>
  688. # if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
  689. # define MAP_ANONYMOUS MAP_ANON
  690. # endif
  691. #endif
  692. ZEND_EXT_API void zend_jit_status(zval *ret)
  693. {
  694. zval stats;
  695. array_init(&stats);
  696. add_assoc_bool(&stats, "enabled", JIT_G(enabled));
  697. add_assoc_bool(&stats, "on", JIT_G(on));
  698. add_assoc_long(&stats, "kind", JIT_G(trigger));
  699. add_assoc_long(&stats, "opt_level", JIT_G(opt_level));
  700. add_assoc_long(&stats, "opt_flags", JIT_G(opt_flags));
  701. if (dasm_buf) {
  702. add_assoc_long(&stats, "buffer_size", (char*)dasm_end - (char*)dasm_buf);
  703. add_assoc_long(&stats, "buffer_free", (char*)dasm_end - (char*)*dasm_ptr);
  704. } else {
  705. add_assoc_long(&stats, "buffer_size", 0);
  706. add_assoc_long(&stats, "buffer_free", 0);
  707. }
  708. add_assoc_zval(ret, "jit", &stats);
  709. }
  710. static zend_string *zend_jit_func_name(const zend_op_array *op_array)
  711. {
  712. smart_str buf = {0};
  713. if (op_array->function_name) {
  714. if (op_array->scope) {
  715. smart_str_appends(&buf, JIT_PREFIX);
  716. smart_str_appendl(&buf, ZSTR_VAL(op_array->scope->name), ZSTR_LEN(op_array->scope->name));
  717. smart_str_appends(&buf, "::");
  718. smart_str_appendl(&buf, ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name));
  719. smart_str_0(&buf);
  720. return buf.s;
  721. } else {
  722. smart_str_appends(&buf, JIT_PREFIX);
  723. smart_str_appendl(&buf, ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name));
  724. smart_str_0(&buf);
  725. return buf.s;
  726. }
  727. } else if (op_array->filename) {
  728. smart_str_appends(&buf, JIT_PREFIX);
  729. smart_str_appendl(&buf, ZSTR_VAL(op_array->filename), ZSTR_LEN(op_array->filename));
  730. smart_str_0(&buf);
  731. return buf.s;
  732. } else {
  733. return NULL;
  734. }
  735. }
  736. #if ZEND_DEBUG
  737. static void handle_dasm_error(int ret) {
  738. switch (ret & 0xff000000u) {
  739. case DASM_S_NOMEM:
  740. fprintf(stderr, "DASM_S_NOMEM\n");
  741. break;
  742. case DASM_S_PHASE:
  743. fprintf(stderr, "DASM_S_PHASE\n");
  744. break;
  745. case DASM_S_MATCH_SEC:
  746. fprintf(stderr, "DASM_S_MATCH_SEC\n");
  747. break;
  748. case DASM_S_RANGE_I:
  749. fprintf(stderr, "DASM_S_RANGE_I\n");
  750. break;
  751. case DASM_S_RANGE_SEC:
  752. fprintf(stderr, "DASM_S_RANGE_SEC\n");
  753. break;
  754. case DASM_S_RANGE_LG:
  755. fprintf(stderr, "DASM_S_RANGE_LG\n");
  756. break;
  757. case DASM_S_RANGE_PC:
  758. fprintf(stderr, "DASM_S_RANGE_PC %d\n", ret & 0xffffffu);
  759. break;
  760. #ifdef DASM_S_RANGE_VREG
  761. case DASM_S_RANGE_VREG:
  762. fprintf(stderr, "DASM_S_RANGE_VREG\n");
  763. break;
  764. #endif
  765. #ifdef DASM_S_UNDEF_L
  766. case DASM_S_UNDEF_L:
  767. fprintf(stderr, "DASM_S_UNDEF_L\n");
  768. break;
  769. #endif
  770. #ifdef DASM_S_UNDEF_LG
  771. case DASM_S_UNDEF_LG:
  772. fprintf(stderr, "DASM_S_UNDEF_LG\n");
  773. break;
  774. #endif
  775. #ifdef DASM_S_RANGE_REL
  776. case DASM_S_RANGE_REL:
  777. fprintf(stderr, "DASM_S_RANGE_REL\n");
  778. break;
  779. #endif
  780. case DASM_S_UNDEF_PC:
  781. fprintf(stderr, "DASM_S_UNDEF_PC\n");
  782. break;
  783. default:
  784. fprintf(stderr, "DASM_S_%0x\n", ret & 0xff000000u);
  785. break;
  786. }
  787. ZEND_UNREACHABLE();
  788. }
  789. #endif
  790. static void *dasm_link_and_encode(dasm_State **dasm_state,
  791. const zend_op_array *op_array,
  792. zend_ssa *ssa,
  793. const zend_op *rt_opline,
  794. zend_lifetime_interval **ra,
  795. const char *name,
  796. uint32_t trace_num,
  797. uint32_t sp_offset,
  798. uint32_t sp_adjustment)
  799. {
  800. size_t size;
  801. int ret;
  802. void *entry;
  803. #if defined(HAVE_DISASM) || defined(HAVE_GDB) || defined(HAVE_OPROFILE) || defined(HAVE_PERFTOOLS) || defined(HAVE_VTUNE)
  804. zend_string *str = NULL;
  805. #endif
  806. if (rt_opline && ssa && ssa->cfg.map) {
  807. /* Create additional entry point, to switch from interpreter to JIT-ed
  808. * code at run-time.
  809. */
  810. int b = ssa->cfg.map[rt_opline - op_array->opcodes];
  811. //#ifdef CONTEXT_THREADED_JIT
  812. // if (!(ssa->cfg.blocks[b].flags & (ZEND_BB_START|ZEND_BB_RECV_ENTRY))) {
  813. //#else
  814. if (!(ssa->cfg.blocks[b].flags & (ZEND_BB_START|ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY))) {
  815. //#endif
  816. zend_jit_label(dasm_state, ssa->cfg.blocks_count + b);
  817. zend_jit_prologue(dasm_state);
  818. if (ra) {
  819. int i;
  820. zend_lifetime_interval *ival;
  821. zend_life_range *range;
  822. uint32_t pos = rt_opline - op_array->opcodes;
  823. for (i = 0; i < ssa->vars_count; i++) {
  824. ival = ra[i];
  825. if (ival && ival->reg != ZREG_NONE) {
  826. range = &ival->range;
  827. if (pos >= range->start && pos <= range->end) {
  828. if (!zend_jit_load_var(dasm_state, ssa->var_info[i].type, ssa->vars[i].var, ival->reg)) {
  829. return NULL;
  830. }
  831. break;
  832. }
  833. range = range->next;
  834. }
  835. }
  836. }
  837. zend_jit_jmp(dasm_state, b);
  838. }
  839. }
  840. ret = dasm_link(dasm_state, &size);
  841. if (ret != DASM_S_OK) {
  842. #if ZEND_DEBUG
  843. handle_dasm_error(ret);
  844. #endif
  845. return NULL;
  846. }
  847. if ((void*)((char*)*dasm_ptr + size) > dasm_end) {
  848. *dasm_ptr = dasm_end; //prevent further try
  849. // TODO: jit_buffer_size overflow ???
  850. return NULL;
  851. }
  852. #if ZEND_JIT_TARGET_ARM64
  853. dasm_venners_size = 0;
  854. #endif
  855. ret = dasm_encode(dasm_state, *dasm_ptr);
  856. if (ret != DASM_S_OK) {
  857. #if ZEND_DEBUG
  858. handle_dasm_error(ret);
  859. #endif
  860. return NULL;
  861. }
  862. #if ZEND_JIT_TARGET_ARM64
  863. size += dasm_venners_size;
  864. #endif
  865. entry = *dasm_ptr;
  866. *dasm_ptr = (void*)((char*)*dasm_ptr + ZEND_MM_ALIGNED_SIZE_EX(size, DASM_ALIGNMENT));
  867. /* flush the hardware I-cache */
  868. JIT_CACHE_FLUSH(entry, entry + size);
  869. if (trace_num) {
  870. zend_jit_trace_add_code(entry, dasm_getpclabel(dasm_state, 1));
  871. }
  872. if (op_array && ssa) {
  873. int b;
  874. for (b = 0; b < ssa->cfg.blocks_count; b++) {
  875. //#ifdef CONTEXT_THREADED_JIT
  876. // if (ssa->cfg.blocks[b].flags & (ZEND_BB_START|ZEND_BB_RECV_ENTRY)) {
  877. //#else
  878. if (ssa->cfg.blocks[b].flags & (ZEND_BB_START|ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
  879. //#endif
  880. zend_op *opline = op_array->opcodes + ssa->cfg.blocks[b].start;
  881. int offset = dasm_getpclabel(dasm_state, ssa->cfg.blocks_count + b);
  882. if (offset >= 0) {
  883. opline->handler = (void*)(((char*)entry) + offset);
  884. }
  885. }
  886. }
  887. if (rt_opline && ssa && ssa->cfg.map) {
  888. int b = ssa->cfg.map[rt_opline - op_array->opcodes];
  889. zend_op *opline = (zend_op*)rt_opline;
  890. int offset = dasm_getpclabel(dasm_state, ssa->cfg.blocks_count + b);
  891. if (offset >= 0) {
  892. opline->handler = (void*)(((char*)entry) + offset);
  893. }
  894. }
  895. }
  896. #if defined(HAVE_DISASM) || defined(HAVE_GDB) || defined(HAVE_OPROFILE) || defined(HAVE_PERFTOOLS) || defined(HAVE_VTUNE)
  897. if (!name) {
  898. if (JIT_G(debug) & (ZEND_JIT_DEBUG_ASM|ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_OPROFILE|ZEND_JIT_DEBUG_PERF|ZEND_JIT_DEBUG_VTUNE|ZEND_JIT_DEBUG_PERF_DUMP)) {
  899. str = zend_jit_func_name(op_array);
  900. if (str) {
  901. name = ZSTR_VAL(str);
  902. }
  903. }
  904. #ifdef HAVE_DISASM
  905. if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM) {
  906. zend_jit_disasm_add_symbol(name, (uintptr_t)entry, size);
  907. zend_jit_disasm(
  908. name,
  909. (op_array && op_array->filename) ? ZSTR_VAL(op_array->filename) : NULL,
  910. op_array,
  911. &ssa->cfg,
  912. entry,
  913. size);
  914. }
  915. } else {
  916. if (JIT_G(debug) & (ZEND_JIT_DEBUG_ASM_STUBS|ZEND_JIT_DEBUG_ASM)) {
  917. zend_jit_disasm_add_symbol(name, (uintptr_t)entry, size);
  918. if ((JIT_G(debug) & (trace_num ? ZEND_JIT_DEBUG_ASM : ZEND_JIT_DEBUG_ASM_STUBS)) != 0) {
  919. zend_jit_disasm(
  920. name,
  921. (op_array && op_array->filename) ? ZSTR_VAL(op_array->filename) : NULL,
  922. op_array,
  923. ssa ? &ssa->cfg : NULL,
  924. entry,
  925. size);
  926. }
  927. }
  928. # endif
  929. }
  930. #endif
  931. #ifdef HAVE_GDB
  932. if (JIT_G(debug) & ZEND_JIT_DEBUG_GDB) {
  933. if (name) {
  934. zend_jit_gdb_register(
  935. name,
  936. op_array,
  937. entry,
  938. size,
  939. sp_adj[sp_offset],
  940. sp_adj[sp_adjustment]);
  941. }
  942. }
  943. #endif
  944. #ifdef HAVE_OPROFILE
  945. if (JIT_G(debug) & ZEND_JIT_DEBUG_OPROFILE) {
  946. zend_jit_oprofile_register(
  947. name,
  948. entry,
  949. size);
  950. }
  951. #endif
  952. #ifdef HAVE_PERFTOOLS
  953. if (JIT_G(debug) & (ZEND_JIT_DEBUG_PERF|ZEND_JIT_DEBUG_PERF_DUMP)) {
  954. if (name) {
  955. zend_jit_perf_map_register(
  956. name,
  957. entry,
  958. size);
  959. if (JIT_G(debug) & ZEND_JIT_DEBUG_PERF_DUMP) {
  960. zend_jit_perf_jitdump_register(
  961. name,
  962. entry,
  963. size);
  964. }
  965. }
  966. }
  967. #endif
  968. #ifdef HAVE_VTUNE
  969. if (JIT_G(debug) & ZEND_JIT_DEBUG_VTUNE) {
  970. if (name) {
  971. zend_jit_vtune_register(
  972. name,
  973. entry,
  974. size);
  975. }
  976. }
  977. #endif
  978. #if defined(HAVE_DISASM) || defined(HAVE_GDB) || defined(HAVE_OPROFILE) || defined(HAVE_PERFTOOLS) || defined(HAVE_VTUNE)
  979. if (str) {
  980. zend_string_release(str);
  981. }
  982. #endif
  983. return entry;
  984. }
  985. static int zend_may_overflow(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, zend_ssa *ssa)
  986. {
  987. int res;
  988. zend_long op1_min, op1_max, op2_min, op2_max;
  989. if (!ssa->ops || !ssa->var_info) {
  990. return 1;
  991. }
  992. switch (opline->opcode) {
  993. case ZEND_PRE_INC:
  994. case ZEND_POST_INC:
  995. res = ssa_op->op1_def;
  996. if (res < 0
  997. || !ssa->var_info[res].has_range
  998. || ssa->var_info[res].range.overflow) {
  999. if (!OP1_HAS_RANGE()) {
  1000. return 1;
  1001. }
  1002. op1_max = OP1_MAX_RANGE();
  1003. if (op1_max == ZEND_LONG_MAX) {
  1004. return 1;
  1005. }
  1006. }
  1007. return 0;
  1008. case ZEND_PRE_DEC:
  1009. case ZEND_POST_DEC:
  1010. res = ssa_op->op1_def;
  1011. if (res < 0
  1012. || !ssa->var_info[res].has_range
  1013. || ssa->var_info[res].range.underflow) {
  1014. if (!OP1_HAS_RANGE()) {
  1015. return 1;
  1016. }
  1017. op1_min = OP1_MIN_RANGE();
  1018. if (op1_min == ZEND_LONG_MIN) {
  1019. return 1;
  1020. }
  1021. }
  1022. return 0;
  1023. case ZEND_ADD:
  1024. res = ssa_op->result_def;
  1025. if (res < 0
  1026. || !ssa->var_info[res].has_range
  1027. || ssa->var_info[res].range.underflow) {
  1028. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1029. return 1;
  1030. }
  1031. op1_min = OP1_MIN_RANGE();
  1032. op2_min = OP2_MIN_RANGE();
  1033. if (zend_add_will_overflow(op1_min, op2_min)) {
  1034. return 1;
  1035. }
  1036. }
  1037. if (res < 0
  1038. || !ssa->var_info[res].has_range
  1039. || ssa->var_info[res].range.overflow) {
  1040. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1041. return 1;
  1042. }
  1043. op1_max = OP1_MAX_RANGE();
  1044. op2_max = OP2_MAX_RANGE();
  1045. if (zend_add_will_overflow(op1_max, op2_max)) {
  1046. return 1;
  1047. }
  1048. }
  1049. return 0;
  1050. case ZEND_SUB:
  1051. res = ssa_op->result_def;
  1052. if (res < 0
  1053. || !ssa->var_info[res].has_range
  1054. || ssa->var_info[res].range.underflow) {
  1055. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1056. return 1;
  1057. }
  1058. op1_min = OP1_MIN_RANGE();
  1059. op2_max = OP2_MAX_RANGE();
  1060. if (zend_sub_will_overflow(op1_min, op2_max)) {
  1061. return 1;
  1062. }
  1063. }
  1064. if (res < 0
  1065. || !ssa->var_info[res].has_range
  1066. || ssa->var_info[res].range.overflow) {
  1067. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1068. return 1;
  1069. }
  1070. op1_max = OP1_MAX_RANGE();
  1071. op2_min = OP2_MIN_RANGE();
  1072. if (zend_sub_will_overflow(op1_max, op2_min)) {
  1073. return 1;
  1074. }
  1075. }
  1076. return 0;
  1077. case ZEND_MUL:
  1078. res = ssa_op->result_def;
  1079. return (res < 0 ||
  1080. !ssa->var_info[res].has_range ||
  1081. ssa->var_info[res].range.underflow ||
  1082. ssa->var_info[res].range.overflow);
  1083. case ZEND_ASSIGN_OP:
  1084. if (opline->extended_value == ZEND_ADD) {
  1085. res = ssa_op->op1_def;
  1086. if (res < 0
  1087. || !ssa->var_info[res].has_range
  1088. || ssa->var_info[res].range.underflow) {
  1089. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1090. return 1;
  1091. }
  1092. op1_min = OP1_MIN_RANGE();
  1093. op2_min = OP2_MIN_RANGE();
  1094. if (zend_add_will_overflow(op1_min, op2_min)) {
  1095. return 1;
  1096. }
  1097. }
  1098. if (res < 0
  1099. || !ssa->var_info[res].has_range
  1100. || ssa->var_info[res].range.overflow) {
  1101. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1102. return 1;
  1103. }
  1104. op1_max = OP1_MAX_RANGE();
  1105. op2_max = OP2_MAX_RANGE();
  1106. if (zend_add_will_overflow(op1_max, op2_max)) {
  1107. return 1;
  1108. }
  1109. }
  1110. return 0;
  1111. } else if (opline->extended_value == ZEND_SUB) {
  1112. res = ssa_op->op1_def;
  1113. if (res < 0
  1114. || !ssa->var_info[res].has_range
  1115. || ssa->var_info[res].range.underflow) {
  1116. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1117. return 1;
  1118. }
  1119. op1_min = OP1_MIN_RANGE();
  1120. op2_max = OP2_MAX_RANGE();
  1121. if (zend_sub_will_overflow(op1_min, op2_max)) {
  1122. return 1;
  1123. }
  1124. }
  1125. if (res < 0
  1126. || !ssa->var_info[res].has_range
  1127. || ssa->var_info[res].range.overflow) {
  1128. if (!OP1_HAS_RANGE() || !OP2_HAS_RANGE()) {
  1129. return 1;
  1130. }
  1131. op1_max = OP1_MAX_RANGE();
  1132. op2_min = OP2_MIN_RANGE();
  1133. if (zend_sub_will_overflow(op1_max, op2_min)) {
  1134. return 1;
  1135. }
  1136. }
  1137. return 0;
  1138. } else if (opline->extended_value == ZEND_MUL) {
  1139. res = ssa_op->op1_def;
  1140. return (res < 0 ||
  1141. !ssa->var_info[res].has_range ||
  1142. ssa->var_info[res].range.underflow ||
  1143. ssa->var_info[res].range.overflow);
  1144. }
  1145. ZEND_FALLTHROUGH;
  1146. default:
  1147. return 1;
  1148. }
  1149. }
  1150. static int zend_jit_build_cfg(const zend_op_array *op_array, zend_cfg *cfg)
  1151. {
  1152. uint32_t flags;
  1153. flags = ZEND_CFG_STACKLESS | ZEND_CFG_NO_ENTRY_PREDECESSORS | ZEND_SSA_RC_INFERENCE_FLAG | ZEND_SSA_USE_CV_RESULTS | ZEND_CFG_RECV_ENTRY;
  1154. if (zend_build_cfg(&CG(arena), op_array, flags, cfg) != SUCCESS) {
  1155. return FAILURE;
  1156. }
  1157. /* Don't JIT huge functions. Apart from likely being detrimental due to the amount of
  1158. * generated code, some of our analysis is recursive and will stack overflow with many
  1159. * blocks. */
  1160. if (cfg->blocks_count > 100000) {
  1161. return FAILURE;
  1162. }
  1163. if (zend_cfg_build_predecessors(&CG(arena), cfg) != SUCCESS) {
  1164. return FAILURE;
  1165. }
  1166. /* Compute Dominators Tree */
  1167. if (zend_cfg_compute_dominators_tree(op_array, cfg) != SUCCESS) {
  1168. return FAILURE;
  1169. }
  1170. /* Identify reducible and irreducible loops */
  1171. if (zend_cfg_identify_loops(op_array, cfg) != SUCCESS) {
  1172. return FAILURE;
  1173. }
  1174. return SUCCESS;
  1175. }
  1176. static int zend_jit_op_array_analyze1(const zend_op_array *op_array, zend_script *script, zend_ssa *ssa)
  1177. {
  1178. if (zend_jit_build_cfg(op_array, &ssa->cfg) != SUCCESS) {
  1179. return FAILURE;
  1180. }
  1181. #if 0
  1182. /* TODO: debugger and profiler supports? */
  1183. if ((ssa->cfg.flags & ZEND_FUNC_HAS_EXTENDED_INFO)) {
  1184. return FAILURE;
  1185. }
  1186. #endif
  1187. /* TODO: move this to zend_cfg.c ? */
  1188. if (!op_array->function_name) {
  1189. ssa->cfg.flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
  1190. }
  1191. if ((JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNC)
  1192. && ssa->cfg.blocks
  1193. && op_array->last_try_catch == 0
  1194. && !(op_array->fn_flags & ZEND_ACC_GENERATOR)
  1195. && !(ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS)) {
  1196. if (zend_build_ssa(&CG(arena), script, op_array, ZEND_SSA_RC_INFERENCE | ZEND_SSA_USE_CV_RESULTS, ssa) != SUCCESS) {
  1197. return FAILURE;
  1198. }
  1199. if (zend_ssa_compute_use_def_chains(&CG(arena), op_array, ssa) != SUCCESS) {
  1200. return FAILURE;
  1201. }
  1202. if (zend_ssa_find_false_dependencies(op_array, ssa) != SUCCESS) {
  1203. return FAILURE;
  1204. }
  1205. if (zend_ssa_find_sccs(op_array, ssa) != SUCCESS){
  1206. return FAILURE;
  1207. }
  1208. }
  1209. return SUCCESS;
  1210. }
  1211. static int zend_jit_op_array_analyze2(const zend_op_array *op_array, zend_script *script, zend_ssa *ssa, uint32_t optimization_level)
  1212. {
  1213. if ((JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNC)
  1214. && ssa->cfg.blocks
  1215. && op_array->last_try_catch == 0
  1216. && !(op_array->fn_flags & ZEND_ACC_GENERATOR)
  1217. && !(ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS)) {
  1218. if (zend_ssa_inference(&CG(arena), op_array, script, ssa,
  1219. optimization_level & ~ZEND_OPTIMIZER_NARROW_TO_DOUBLE) != SUCCESS) {
  1220. return FAILURE;
  1221. }
  1222. }
  1223. return SUCCESS;
  1224. }
  1225. static int zend_jit_add_range(zend_lifetime_interval **intervals, int var, uint32_t from, uint32_t to)
  1226. {
  1227. zend_lifetime_interval *ival = intervals[var];
  1228. if (!ival) {
  1229. ival = zend_arena_alloc(&CG(arena), sizeof(zend_lifetime_interval));
  1230. if (!ival) {
  1231. return FAILURE;
  1232. }
  1233. ival->ssa_var = var;
  1234. ival->reg = ZREG_NONE;
  1235. ival->flags = 0;
  1236. ival->range.start = from;
  1237. ival->range.end = to;
  1238. ival->range.next = NULL;
  1239. ival->hint = NULL;
  1240. ival->used_as_hint = NULL;
  1241. intervals[var] = ival;
  1242. } else if (ival->range.start > to + 1) {
  1243. zend_life_range *range = zend_arena_alloc(&CG(arena), sizeof(zend_life_range));
  1244. if (!range) {
  1245. return FAILURE;
  1246. }
  1247. range->start = ival->range.start;
  1248. range->end = ival->range.end;
  1249. range->next = ival->range.next;
  1250. ival->range.start = from;
  1251. ival->range.end = to;
  1252. ival->range.next = range;
  1253. } else if (ival->range.start == to + 1) {
  1254. ival->range.start = from;
  1255. } else {
  1256. zend_life_range *range = &ival->range;
  1257. zend_life_range *last = NULL;
  1258. do {
  1259. if (range->start > to + 1) {
  1260. break;
  1261. } else if (range->end + 1 >= from) {
  1262. if (range->start > from) {
  1263. range->start = from;
  1264. }
  1265. last = range;
  1266. range = range->next;
  1267. while (range) {
  1268. if (range->start > to + 1) {
  1269. break;
  1270. }
  1271. last->end = range->end;
  1272. range = range->next;
  1273. last->next = range;
  1274. }
  1275. if (to > last->end) {
  1276. last->end = to;
  1277. }
  1278. return SUCCESS;
  1279. }
  1280. last = range;
  1281. range = range->next;
  1282. } while (range);
  1283. range = zend_arena_alloc(&CG(arena), sizeof(zend_life_range));
  1284. if (!range) {
  1285. return FAILURE;
  1286. }
  1287. range->start = from;
  1288. range->end = to;
  1289. range->next = last->next;
  1290. last->next = range;
  1291. }
  1292. return SUCCESS;
  1293. }
  1294. static int zend_jit_begin_range(zend_lifetime_interval **intervals, int var, uint32_t block_start, uint32_t from)
  1295. {
  1296. if (block_start != from && intervals[var]) {
  1297. zend_life_range *range = &intervals[var]->range;
  1298. do {
  1299. if (from >= range->start && from <= range->end) {
  1300. if (range->start == block_start) {
  1301. range->start = from;
  1302. } else {
  1303. zend_life_range *r = zend_arena_alloc(&CG(arena), sizeof(zend_life_range));
  1304. if (!r) {
  1305. return FAILURE;
  1306. }
  1307. r->start = from;
  1308. r->end = range->end;
  1309. r->next = range->next;
  1310. range->end = block_start - 1;
  1311. range->next = r;
  1312. }
  1313. return SUCCESS;
  1314. }
  1315. range = range->next;
  1316. } while (range);
  1317. }
  1318. // dead store
  1319. return zend_jit_add_range(intervals, var, from, from);
  1320. }
  1321. static void zend_jit_insert_interval(zend_lifetime_interval **list, zend_lifetime_interval *ival)
  1322. {
  1323. while (1) {
  1324. if (*list == NULL) {
  1325. *list = ival;
  1326. ival->list_next = NULL;
  1327. return;
  1328. } else if (ival->range.start < (*list)->range.start) {
  1329. ival->list_next = *list;
  1330. *list = ival;
  1331. return;
  1332. }
  1333. list = &(*list)->list_next;
  1334. }
  1335. }
  1336. static int zend_jit_split_interval(zend_lifetime_interval *current, uint32_t pos, zend_lifetime_interval **list, zend_lifetime_interval **free)
  1337. {
  1338. zend_lifetime_interval *ival;
  1339. zend_life_range *range = &current->range;
  1340. zend_life_range *prev = NULL;
  1341. if (*free) {
  1342. ival = *free;
  1343. *free = ival->list_next;
  1344. } else {
  1345. ival = zend_arena_alloc(&CG(arena), sizeof(zend_lifetime_interval));
  1346. if (!ival) {
  1347. return FAILURE;
  1348. }
  1349. }
  1350. current->flags |= ZREG_STORE;
  1351. ival->ssa_var = current->ssa_var;
  1352. ival->reg = ZREG_NONE;
  1353. ival->flags |= ZREG_SPLIT | ZREG_LOAD;
  1354. ival->flags &= ~ZREG_STORE;
  1355. ival->hint = NULL;
  1356. do {
  1357. if (pos >= range->start && pos <= range->end) {
  1358. break;
  1359. }
  1360. prev = range;
  1361. range = range->next;
  1362. } while(range);
  1363. ZEND_ASSERT(range != NULL);
  1364. ival->range.start = pos;
  1365. ival->range.end = range->end;
  1366. ival->range.next = range->next;
  1367. if (pos == range->start) {
  1368. ZEND_ASSERT(prev != NULL);
  1369. prev->next = NULL;
  1370. } else {
  1371. range->end = pos - 1;
  1372. }
  1373. zend_jit_insert_interval(list, ival);
  1374. return SUCCESS;
  1375. }
  1376. static zend_lifetime_interval *zend_jit_sort_intervals(zend_lifetime_interval **intervals, int count)
  1377. {
  1378. zend_lifetime_interval *list, *last;
  1379. int i;
  1380. list = NULL;
  1381. i = 0;
  1382. while (i < count) {
  1383. list = intervals[i];
  1384. i++;
  1385. if (list) {
  1386. last = list;
  1387. last->list_next = NULL;
  1388. break;
  1389. }
  1390. }
  1391. while (i < count) {
  1392. zend_lifetime_interval *ival = intervals[i];
  1393. i++;
  1394. if (ival) {
  1395. if ((ival->range.start > last->range.start) ||
  1396. (ival->range.start == last->range.start &&
  1397. ((!ival->hint && last->hint && last->hint != ival) ||
  1398. ival->range.end > last->range.end))) {
  1399. last->list_next = ival;
  1400. last = ival;
  1401. ival->list_next = NULL;
  1402. } else {
  1403. zend_lifetime_interval **p = &list;
  1404. while (1) {
  1405. if (*p == NULL) {
  1406. *p = last = ival;
  1407. ival->list_next = NULL;
  1408. break;
  1409. } else if ((ival->range.start < (*p)->range.start) ||
  1410. (ival->range.start == (*p)->range.start &&
  1411. ((ival->hint && !(*p)->hint && ival->hint != *p) ||
  1412. ival->range.end < (*p)->range.end))) {
  1413. ival->list_next = *p;
  1414. *p = ival;
  1415. break;
  1416. }
  1417. p = &(*p)->list_next;
  1418. }
  1419. }
  1420. }
  1421. }
  1422. return list;
  1423. }
  1424. static ZEND_ATTRIBUTE_UNUSED void zend_jit_print_regset(zend_regset regset)
  1425. {
  1426. zend_reg reg;
  1427. int first = 1;
  1428. ZEND_REGSET_FOREACH(regset, reg) {
  1429. if (first) {
  1430. first = 0;
  1431. fprintf(stderr, "%s", zend_reg_name[reg]);
  1432. } else {
  1433. fprintf(stderr, ", %s", zend_reg_name[reg]);
  1434. }
  1435. } ZEND_REGSET_FOREACH_END();
  1436. }
  1437. static int *zend_jit_compute_block_order_int(zend_ssa *ssa, int n, int *block_order)
  1438. {
  1439. zend_basic_block *b = ssa->cfg.blocks + n;
  1440. tail_call:
  1441. *block_order = n;
  1442. block_order++;
  1443. n = b->children;
  1444. while (n >= 0) {
  1445. b = ssa->cfg.blocks + n;
  1446. if (b->next_child < 0) {
  1447. goto tail_call;
  1448. }
  1449. block_order = zend_jit_compute_block_order_int(ssa, n, block_order);
  1450. n = b->next_child;
  1451. }
  1452. return block_order;
  1453. }
  1454. static int zend_jit_compute_block_order(zend_ssa *ssa, int *block_order)
  1455. {
  1456. int *end = zend_jit_compute_block_order_int(ssa, 0, block_order);
  1457. return end - block_order;
  1458. }
  1459. static bool zend_jit_in_loop(zend_ssa *ssa, int header, zend_basic_block *b)
  1460. {
  1461. while (b->loop_header >= 0) {
  1462. if (b->loop_header == header) {
  1463. return 1;
  1464. }
  1465. b = ssa->cfg.blocks + b->loop_header;
  1466. }
  1467. return 0;
  1468. }
  1469. static void zend_jit_compute_loop_body(zend_ssa *ssa, int header, int n, zend_bitset loop_body)
  1470. {
  1471. zend_basic_block *b = ssa->cfg.blocks + n;
  1472. uint32_t i;
  1473. tail_call:
  1474. if (b->len) {
  1475. for (i = b->start; i < b->start + b->len; i++) {
  1476. zend_bitset_incl(loop_body, i);
  1477. }
  1478. }
  1479. n = b->children;
  1480. while (n >= 0) {
  1481. b = ssa->cfg.blocks + n;
  1482. if (zend_jit_in_loop(ssa, header, b)) {
  1483. if (b->next_child < 0) {
  1484. goto tail_call;
  1485. }
  1486. zend_jit_compute_loop_body(ssa, header, n, loop_body);
  1487. }
  1488. n = b->next_child;
  1489. }
  1490. }
  1491. static void zend_jit_add_hint(zend_lifetime_interval **intervals, int dst, int src)
  1492. {
  1493. if (intervals[dst]->range.start < intervals[src]->range.start) {
  1494. int tmp = src;
  1495. src = dst;
  1496. dst = tmp;
  1497. }
  1498. while (dst != src && intervals[dst]->hint) {
  1499. if (intervals[dst]->hint->range.start < intervals[src]->range.start) {
  1500. int tmp = src;
  1501. src = intervals[dst]->hint->ssa_var;
  1502. dst = tmp;
  1503. } else {
  1504. dst = intervals[dst]->hint->ssa_var;
  1505. }
  1506. }
  1507. if (dst != src) {
  1508. intervals[dst]->hint = intervals[src];
  1509. }
  1510. }
  1511. /* See "Linear Scan Register Allocation on SSA Form", Christian Wimmer and
  1512. Michael Franz, CGO'10 (2010), Figure 4. */
  1513. static int zend_jit_compute_liveness(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset candidates, zend_lifetime_interval **list)
  1514. {
  1515. int set_size, i, j, k, l;
  1516. uint32_t n;
  1517. zend_bitset live, live_in, pi_vars, loop_body;
  1518. int *block_order;
  1519. zend_ssa_phi *phi;
  1520. zend_lifetime_interval **intervals;
  1521. size_t mem_size;
  1522. ALLOCA_FLAG(use_heap);
  1523. set_size = zend_bitset_len(ssa->vars_count);
  1524. mem_size =
  1525. ZEND_MM_ALIGNED_SIZE(ssa->vars_count * sizeof(zend_lifetime_interval*)) +
  1526. ZEND_MM_ALIGNED_SIZE((set_size * ssa->cfg.blocks_count) * ZEND_BITSET_ELM_SIZE) +
  1527. ZEND_MM_ALIGNED_SIZE(set_size * ZEND_BITSET_ELM_SIZE) +
  1528. ZEND_MM_ALIGNED_SIZE(set_size * ZEND_BITSET_ELM_SIZE) +
  1529. ZEND_MM_ALIGNED_SIZE(zend_bitset_len(op_array->last) * ZEND_BITSET_ELM_SIZE) +
  1530. ZEND_MM_ALIGNED_SIZE(ssa->cfg.blocks_count * sizeof(int));
  1531. intervals = do_alloca(mem_size, use_heap);
  1532. if (!intervals) {
  1533. *list = NULL;
  1534. return FAILURE;
  1535. }
  1536. live_in = (zend_bitset)((char*)intervals + ZEND_MM_ALIGNED_SIZE(ssa->vars_count * sizeof(zend_lifetime_interval*)));
  1537. live = (zend_bitset)((char*)live_in + ZEND_MM_ALIGNED_SIZE((set_size * ssa->cfg.blocks_count) * ZEND_BITSET_ELM_SIZE));
  1538. pi_vars = (zend_bitset)((char*)live + ZEND_MM_ALIGNED_SIZE(set_size * ZEND_BITSET_ELM_SIZE));
  1539. loop_body = (zend_bitset)((char*)pi_vars + ZEND_MM_ALIGNED_SIZE(set_size * ZEND_BITSET_ELM_SIZE));
  1540. block_order = (int*)((char*)loop_body + ZEND_MM_ALIGNED_SIZE(zend_bitset_len(op_array->last) * ZEND_BITSET_ELM_SIZE));
  1541. memset(intervals, 0, ssa->vars_count * sizeof(zend_lifetime_interval*));
  1542. zend_bitset_clear(live_in, set_size * ssa->cfg.blocks_count);
  1543. /* TODO: Provide a linear block order where all dominators of a block
  1544. * are before this block, and where all blocks belonging to the same loop
  1545. * are contiguous ???
  1546. */
  1547. for (l = zend_jit_compute_block_order(ssa, block_order) - 1; l >= 0; l--) {
  1548. zend_basic_block *b;
  1549. i = block_order[l];
  1550. b = ssa->cfg.blocks + i;
  1551. /* live = UNION of successor.liveIn for each successor of b */
  1552. /* live.add(phi.inputOf(b)) for each phi of successors of b */
  1553. zend_bitset_clear(live, set_size);
  1554. for (j = 0; j < b->successors_count; j++) {
  1555. int succ = b->successors[j];
  1556. zend_bitset_union(live, live_in + set_size * succ, set_size);
  1557. zend_bitset_clear(pi_vars, set_size);
  1558. for (phi = ssa->blocks[succ].phis; phi; phi = phi->next) {
  1559. if (ssa->vars[phi->ssa_var].no_val) {
  1560. /* skip */
  1561. } else if (phi->pi >= 0) {
  1562. if (phi->pi == i && phi->sources[0] >= 0) {
  1563. if (zend_bitset_in(candidates, phi->sources[0])) {
  1564. zend_bitset_incl(live, phi->sources[0]);
  1565. }
  1566. zend_bitset_incl(pi_vars, phi->var);
  1567. }
  1568. } else if (!zend_bitset_in(pi_vars, phi->var)) {
  1569. for (k = 0; k < ssa->cfg.blocks[succ].predecessors_count; k++) {
  1570. if (ssa->cfg.predecessors[ssa->cfg.blocks[succ].predecessor_offset + k] == i) {
  1571. if (phi->sources[k] >= 0 && zend_bitset_in(candidates, phi->sources[k])) {
  1572. zend_bitset_incl(live, phi->sources[k]);
  1573. }
  1574. break;
  1575. }
  1576. }
  1577. }
  1578. }
  1579. }
  1580. /* addRange(var, b.from, b.to) for each var in live */
  1581. ZEND_BITSET_FOREACH(live, set_size, j) {
  1582. if (zend_bitset_in(candidates, j)) {
  1583. if (zend_jit_add_range(intervals, j, b->start, b->start + b->len - 1) != SUCCESS) {
  1584. goto failure;
  1585. }
  1586. }
  1587. } ZEND_BITSET_FOREACH_END();
  1588. /* for each operation op of b in reverse order */
  1589. for (n = b->start + b->len; n > b->start;) {
  1590. zend_ssa_op *op;
  1591. const zend_op *opline;
  1592. uint32_t num;
  1593. n--;
  1594. op = ssa->ops + n;
  1595. opline = op_array->opcodes + n;
  1596. if (UNEXPECTED(opline->opcode == ZEND_OP_DATA)) {
  1597. num = n - 1;
  1598. } else {
  1599. num = n;
  1600. }
  1601. /* for each output operand opd of op do */
  1602. /* setFrom(opd, op) */
  1603. /* live.remove(opd) */
  1604. if (op->op1_def >= 0 && zend_bitset_in(candidates, op->op1_def)) {
  1605. if (zend_jit_begin_range(intervals, op->op1_def, b->start, num) != SUCCESS) {
  1606. goto failure;
  1607. }
  1608. zend_bitset_excl(live, op->op1_def);
  1609. }
  1610. if (op->op2_def >= 0 && zend_bitset_in(candidates, op->op2_def)) {
  1611. if (zend_jit_begin_range(intervals, op->op2_def, b->start, num) != SUCCESS) {
  1612. goto failure;
  1613. }
  1614. zend_bitset_excl(live, op->op2_def);
  1615. }
  1616. if (op->result_def >= 0 && zend_bitset_in(candidates, op->result_def)) {
  1617. if (zend_jit_begin_range(intervals, op->result_def, b->start, num) != SUCCESS) {
  1618. goto failure;
  1619. }
  1620. zend_bitset_excl(live, op->result_def);
  1621. }
  1622. /* for each input operand opd of op do */
  1623. /* live.add(opd) */
  1624. /* addRange(opd, b.from, op) */
  1625. if (op->op1_use >= 0
  1626. && zend_bitset_in(candidates, op->op1_use)
  1627. && !zend_ssa_is_no_val_use(opline, op, op->op1_use)) {
  1628. zend_bitset_incl(live, op->op1_use);
  1629. if (zend_jit_add_range(intervals, op->op1_use, b->start, num) != SUCCESS) {
  1630. goto failure;
  1631. }
  1632. }
  1633. if (op->op2_use >= 0
  1634. && zend_bitset_in(candidates, op->op2_use)
  1635. && !zend_ssa_is_no_val_use(opline, op, op->op2_use)) {
  1636. zend_bitset_incl(live, op->op2_use);
  1637. if (zend_jit_add_range(intervals, op->op2_use, b->start, num) != SUCCESS) {
  1638. goto failure;
  1639. }
  1640. }
  1641. if (op->result_use >= 0
  1642. && zend_bitset_in(candidates, op->result_use)
  1643. && !zend_ssa_is_no_val_use(opline, op, op->result_use)) {
  1644. zend_bitset_incl(live, op->result_use);
  1645. if (zend_jit_add_range(intervals, op->result_use, b->start, num) != SUCCESS) {
  1646. goto failure;
  1647. }
  1648. }
  1649. }
  1650. /* live.remove(phi.output) for each phi of b */
  1651. for (phi = ssa->blocks[i].phis; phi; phi = phi->next) {
  1652. zend_bitset_excl(live, phi->ssa_var);
  1653. }
  1654. /* b.liveIn = live */
  1655. zend_bitset_copy(live_in + set_size * i, live, set_size);
  1656. }
  1657. for (i = ssa->cfg.blocks_count - 1; i >= 0; i--) {
  1658. zend_basic_block *b = ssa->cfg.blocks + i;
  1659. /* if b is loop header */
  1660. if ((b->flags & ZEND_BB_LOOP_HEADER)) {
  1661. live = live_in + set_size * i;
  1662. if (!zend_bitset_empty(live, set_size)) {
  1663. uint32_t set_size2 = zend_bitset_len(op_array->last);
  1664. zend_bitset_clear(loop_body, set_size2);
  1665. zend_jit_compute_loop_body(ssa, i, i, loop_body);
  1666. while (!zend_bitset_empty(loop_body, set_size2)) {
  1667. uint32_t from = zend_bitset_first(loop_body, set_size2);
  1668. uint32_t to = from;
  1669. do {
  1670. zend_bitset_excl(loop_body, to);
  1671. to++;
  1672. } while (zend_bitset_in(loop_body, to));
  1673. to--;
  1674. ZEND_BITSET_FOREACH(live, set_size, j) {
  1675. if (zend_jit_add_range(intervals, j, from, to) != SUCCESS) {
  1676. goto failure;
  1677. }
  1678. } ZEND_BITSET_FOREACH_END();
  1679. }
  1680. }
  1681. }
  1682. }
  1683. if (JIT_G(opt_flags) & ZEND_JIT_REG_ALLOC_GLOBAL) {
  1684. /* Register hinting (a cheap way for register coalescing) */
  1685. for (i = 0; i < ssa->vars_count; i++) {
  1686. if (intervals[i]) {
  1687. int src;
  1688. if (ssa->vars[i].definition_phi) {
  1689. zend_ssa_phi *phi = ssa->vars[i].definition_phi;
  1690. if (phi->pi >= 0) {
  1691. src = phi->sources[0];
  1692. if (intervals[src]) {
  1693. zend_jit_add_hint(intervals, i, src);
  1694. }
  1695. } else {
  1696. for (k = 0; k < ssa->cfg.blocks[phi->block].predecessors_count; k++) {
  1697. src = phi->sources[k];
  1698. if (src >= 0) {
  1699. if (ssa->vars[src].definition_phi
  1700. && ssa->vars[src].definition_phi->pi >= 0
  1701. && phi->block == ssa->vars[src].definition_phi->block) {
  1702. /* Skip zero-length interval for Pi variable */
  1703. src = ssa->vars[src].definition_phi->sources[0];
  1704. }
  1705. if (intervals[src]) {
  1706. zend_jit_add_hint(intervals, i, src);
  1707. }
  1708. }
  1709. }
  1710. }
  1711. }
  1712. }
  1713. }
  1714. for (i = 0; i < ssa->vars_count; i++) {
  1715. if (intervals[i] && !intervals[i]->hint) {
  1716. if (ssa->vars[i].definition >= 0) {
  1717. uint32_t line = ssa->vars[i].definition;
  1718. const zend_op *opline = op_array->opcodes + line;
  1719. switch (opline->opcode) {
  1720. case ZEND_QM_ASSIGN:
  1721. case ZEND_POST_INC:
  1722. case ZEND_POST_DEC:
  1723. if (ssa->ops[line].op1_use >= 0 &&
  1724. intervals[ssa->ops[line].op1_use] &&
  1725. (i == ssa->ops[line].op1_def ||
  1726. (i == ssa->ops[line].result_def &&
  1727. (ssa->ops[line].op1_def < 0 ||
  1728. !intervals[ssa->ops[line].op1_def])))) {
  1729. zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use);
  1730. }
  1731. break;
  1732. case ZEND_SEND_VAR:
  1733. case ZEND_PRE_INC:
  1734. case ZEND_PRE_DEC:
  1735. if (i == ssa->ops[line].op1_def &&
  1736. ssa->ops[line].op1_use >= 0 &&
  1737. intervals[ssa->ops[line].op1_use]) {
  1738. zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use);
  1739. }
  1740. break;
  1741. case ZEND_ASSIGN:
  1742. if (ssa->ops[line].op2_use >= 0 &&
  1743. intervals[ssa->ops[line].op2_use] &&
  1744. (i == ssa->ops[line].op2_def ||
  1745. (i == ssa->ops[line].op1_def &&
  1746. (ssa->ops[line].op2_def < 0 ||
  1747. !intervals[ssa->ops[line].op2_def])) ||
  1748. (i == ssa->ops[line].result_def &&
  1749. (ssa->ops[line].op2_def < 0 ||
  1750. !intervals[ssa->ops[line].op2_def]) &&
  1751. (ssa->ops[line].op1_def < 0 ||
  1752. !intervals[ssa->ops[line].op1_def])))) {
  1753. zend_jit_add_hint(intervals, i, ssa->ops[line].op2_use);
  1754. }
  1755. break;
  1756. case ZEND_SUB:
  1757. case ZEND_ADD:
  1758. case ZEND_MUL:
  1759. case ZEND_BW_OR:
  1760. case ZEND_BW_AND:
  1761. case ZEND_BW_XOR:
  1762. if (i == ssa->ops[line].result_def) {
  1763. if (ssa->ops[line].op1_use >= 0 &&
  1764. intervals[ssa->ops[line].op1_use] &&
  1765. ssa->ops[line].op1_use_chain < 0 &&
  1766. !ssa->vars[ssa->ops[line].op1_use].phi_use_chain &&
  1767. (ssa->var_info[i].type & MAY_BE_ANY) ==
  1768. (ssa->var_info[ssa->ops[line].op1_use].type & MAY_BE_ANY)) {
  1769. zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use);
  1770. } else if (opline->opcode != ZEND_SUB &&
  1771. ssa->ops[line].op2_use >= 0 &&
  1772. intervals[ssa->ops[line].op2_use] &&
  1773. ssa->ops[line].op2_use_chain < 0 &&
  1774. !ssa->vars[ssa->ops[line].op2_use].phi_use_chain &&
  1775. (ssa->var_info[i].type & MAY_BE_ANY) ==
  1776. (ssa->var_info[ssa->ops[line].op2_use].type & MAY_BE_ANY)) {
  1777. zend_jit_add_hint(intervals, i, ssa->ops[line].op2_use);
  1778. }
  1779. }
  1780. break;
  1781. }
  1782. }
  1783. }
  1784. }
  1785. }
  1786. *list = zend_jit_sort_intervals(intervals, ssa->vars_count);
  1787. if (*list) {
  1788. zend_lifetime_interval *ival = *list;
  1789. while (ival) {
  1790. if (ival->hint) {
  1791. ival->hint->used_as_hint = ival;
  1792. }
  1793. ival = ival->list_next;
  1794. }
  1795. }
  1796. free_alloca(intervals, use_heap);
  1797. return SUCCESS;
  1798. failure:
  1799. *list = NULL;
  1800. free_alloca(intervals, use_heap);
  1801. return FAILURE;
  1802. }
  1803. static uint32_t zend_interval_end(zend_lifetime_interval *ival)
  1804. {
  1805. zend_life_range *range = &ival->range;
  1806. while (range->next) {
  1807. range = range->next;
  1808. }
  1809. return range->end;
  1810. }
  1811. static bool zend_interval_covers(zend_lifetime_interval *ival, uint32_t position)
  1812. {
  1813. zend_life_range *range = &ival->range;
  1814. do {
  1815. if (position >= range->start && position <= range->end) {
  1816. return 1;
  1817. }
  1818. range = range->next;
  1819. } while (range);
  1820. return 0;
  1821. }
  1822. static uint32_t zend_interval_intersection(zend_lifetime_interval *ival1, zend_lifetime_interval *ival2)
  1823. {
  1824. zend_life_range *r1 = &ival1->range;
  1825. zend_life_range *r2 = &ival2->range;
  1826. do {
  1827. if (r1->start <= r2->end) {
  1828. if (r2->start <= r1->end) {
  1829. return MAX(r1->start, r2->start);
  1830. } else {
  1831. r2 = r2->next;
  1832. }
  1833. } else {
  1834. r1 = r1->next;
  1835. }
  1836. } while (r1 && r2);
  1837. return 0xffffffff;
  1838. }
  1839. /* See "Optimized Interval Splitting in a Linear Scan Register Allocator",
  1840. Christian Wimmer VEE'05 (2005), Figure 4. Allocation without spilling */
  1841. static int zend_jit_try_allocate_free_reg(const zend_op_array *op_array, const zend_op **ssa_opcodes, zend_ssa *ssa, zend_lifetime_interval *current, zend_regset available, zend_regset *hints, zend_lifetime_interval *active, zend_lifetime_interval *inactive, zend_lifetime_interval **list, zend_lifetime_interval **free)
  1842. {
  1843. zend_lifetime_interval *it;
  1844. uint32_t freeUntilPos[ZREG_NUM];
  1845. uint32_t pos, pos2;
  1846. zend_reg i, reg, reg2;
  1847. zend_reg hint = ZREG_NONE;
  1848. zend_regset low_priority_regs;
  1849. zend_life_range *range;
  1850. if ((ssa->var_info[current->ssa_var].type & MAY_BE_ANY) == MAY_BE_DOUBLE) {
  1851. available = ZEND_REGSET_INTERSECTION(available, ZEND_REGSET_FP);
  1852. } else {
  1853. available = ZEND_REGSET_INTERSECTION(available, ZEND_REGSET_GP);
  1854. }
  1855. /* TODO: Allow usage of preserved registers ???
  1856. * Their values have to be stored in prologue and restored in epilogue
  1857. */
  1858. available = ZEND_REGSET_DIFFERENCE(available, ZEND_REGSET_PRESERVED);
  1859. /* Set freeUntilPos of all physical registers to maxInt */
  1860. for (i = 0; i < ZREG_NUM; i++) {
  1861. freeUntilPos[i] = 0xffffffff;
  1862. }
  1863. /* for each interval it in active do */
  1864. /* freeUntilPos[it.reg] = 0 */
  1865. it = active;
  1866. if (ssa->vars[current->ssa_var].definition == current->range.start) {
  1867. while (it) {
  1868. if (current->range.start != zend_interval_end(it)) {
  1869. freeUntilPos[it->reg] = 0;
  1870. } else if (zend_jit_may_reuse_reg(
  1871. ssa_opcodes ? ssa_opcodes[current->range.start] : op_array->opcodes + current->range.start,
  1872. ssa->ops + current->range.start, ssa, current->ssa_var, it->ssa_var)) {
  1873. if (!ZEND_REGSET_IN(*hints, it->reg) &&
  1874. /* TODO: Avoid most often scratch registers. Find a better way ??? */
  1875. (!current->used_as_hint ||
  1876. !ZEND_REGSET_IN(ZEND_REGSET_LOW_PRIORITY, it->reg))) {
  1877. hint = it->reg;
  1878. }
  1879. } else {
  1880. freeUntilPos[it->reg] = 0;
  1881. }
  1882. it = it->list_next;
  1883. }
  1884. } else {
  1885. while (it) {
  1886. freeUntilPos[it->reg] = 0;
  1887. it = it->list_next;
  1888. }
  1889. }
  1890. if (current->hint) {
  1891. hint = current->hint->reg;
  1892. if (hint != ZREG_NONE && current->hint->used_as_hint == current) {
  1893. ZEND_REGSET_EXCL(*hints, hint);
  1894. }
  1895. }
  1896. if (hint == ZREG_NONE && ZEND_REGSET_IS_EMPTY(available)) {
  1897. return 0;
  1898. }
  1899. /* See "Linear Scan Register Allocation on SSA Form", Christian Wimmer and
  1900. Michael Franz, CGO'10 (2010), Figure 6. */
  1901. if (current->flags & ZREG_SPLIT) {
  1902. /* for each interval it in inactive intersecting with current do */
  1903. /* freeUntilPos[it.reg] = next intersection of it with current */
  1904. it = inactive;
  1905. while (it) {
  1906. uint32_t next = zend_interval_intersection(current, it);
  1907. //ZEND_ASSERT(next != 0xffffffff && !current->split);
  1908. if (next < freeUntilPos[it->reg]) {
  1909. freeUntilPos[it->reg] = next;
  1910. }
  1911. it = it->list_next;
  1912. }
  1913. }
  1914. /* Handle Scratch Registers */
  1915. /* TODO: Optimize ??? */
  1916. range = &current->range;
  1917. do {
  1918. uint32_t line = range->start;
  1919. uint32_t last_use_line = (uint32_t)-1;
  1920. zend_regset regset;
  1921. zend_reg reg;
  1922. if ((current->flags & ZREG_LAST_USE) && !range->next) {
  1923. last_use_line = range->end;
  1924. }
  1925. if (ssa->ops[line].op1_def == current->ssa_var ||
  1926. ssa->ops[line].op2_def == current->ssa_var ||
  1927. ssa->ops[line].result_def == current->ssa_var) {
  1928. regset = zend_jit_get_def_scratch_regset(
  1929. ssa_opcodes ? ssa_opcodes[line] : op_array->opcodes + line,
  1930. ssa->ops + line,
  1931. op_array, ssa, current->ssa_var, line == last_use_line);
  1932. ZEND_REGSET_FOREACH(regset, reg) {
  1933. if (line < freeUntilPos[reg]) {
  1934. freeUntilPos[reg] = line;
  1935. }
  1936. } ZEND_REGSET_FOREACH_END();
  1937. line++;
  1938. }
  1939. while (line <= range->end) {
  1940. regset = zend_jit_get_scratch_regset(
  1941. ssa_opcodes ? ssa_opcodes[line] : op_array->opcodes + line,
  1942. ssa->ops + line,
  1943. op_array, ssa, current->ssa_var, line == last_use_line);
  1944. ZEND_REGSET_FOREACH(regset, reg) {
  1945. if (line < freeUntilPos[reg]) {
  1946. freeUntilPos[reg] = line;
  1947. }
  1948. } ZEND_REGSET_FOREACH_END();
  1949. line++;
  1950. }
  1951. range = range->next;
  1952. } while (range);
  1953. #if 0
  1954. /* Coalescing */
  1955. if (ssa->vars[current->ssa_var].definition == current->start) {
  1956. zend_op *opline = op_array->opcodes + current->start;
  1957. int hint = -1;
  1958. switch (opline->opcode) {
  1959. case ZEND_ASSIGN:
  1960. hint = ssa->ops[current->start].op2_use;
  1961. case ZEND_QM_ASSIGN:
  1962. hint = ssa->ops[current->start].op1_use;
  1963. break;
  1964. case ZEND_ADD:
  1965. case ZEND_SUB:
  1966. case ZEND_MUL:
  1967. hint = ssa->ops[current->start].op1_use;
  1968. break;
  1969. case ZEND_ASSIGN_OP:
  1970. if (opline->extended_value == ZEND_ADD
  1971. || opline->extended_value == ZEND_SUB
  1972. || opline->extended_value == ZEND_MUL) {
  1973. hint = ssa->ops[current->start].op1_use;
  1974. }
  1975. break;
  1976. }
  1977. if (hint >= 0) {
  1978. }
  1979. }
  1980. #endif
  1981. if (hint != ZREG_NONE && freeUntilPos[hint] > zend_interval_end(current)) {
  1982. current->reg = hint;
  1983. if (current->used_as_hint) {
  1984. ZEND_REGSET_INCL(*hints, hint);
  1985. }
  1986. return 1;
  1987. }
  1988. if (ZEND_REGSET_IS_EMPTY(available)) {
  1989. return 0;
  1990. }
  1991. pos = 0; reg = ZREG_NONE;
  1992. pos2 = 0; reg2 = ZREG_NONE;
  1993. low_priority_regs = *hints;
  1994. if (current->used_as_hint) {
  1995. /* TODO: Avoid most often scratch registers. Find a better way ??? */
  1996. low_priority_regs = ZEND_REGSET_UNION(low_priority_regs, ZEND_REGSET_LOW_PRIORITY);
  1997. }
  1998. ZEND_REGSET_FOREACH(available, i) {
  1999. if (ZEND_REGSET_IN(low_priority_regs, i)) {
  2000. if (freeUntilPos[i] > pos2) {
  2001. reg2 = i;
  2002. pos2 = freeUntilPos[i];
  2003. }
  2004. } else if (freeUntilPos[i] > pos) {
  2005. reg = i;
  2006. pos = freeUntilPos[i];
  2007. }
  2008. } ZEND_REGSET_FOREACH_END();
  2009. if (reg == ZREG_NONE) {
  2010. if (reg2 != ZREG_NONE) {
  2011. reg = reg2;
  2012. pos = pos2;
  2013. reg2 = ZREG_NONE;
  2014. }
  2015. }
  2016. if (reg == ZREG_NONE) {
  2017. /* no register available without spilling */
  2018. return 0;
  2019. } else if (zend_interval_end(current) < pos) {
  2020. /* register available for the whole interval */
  2021. current->reg = reg;
  2022. if (current->used_as_hint) {
  2023. ZEND_REGSET_INCL(*hints, reg);
  2024. }
  2025. return 1;
  2026. #if 0
  2027. // TODO: allow low priority register usage
  2028. } else if (reg2 != ZREG_NONE && zend_interval_end(current) < pos2) {
  2029. /* register available for the whole interval */
  2030. current->reg = reg2;
  2031. if (current->used_as_hint) {
  2032. ZEND_REGSET_INCL(*hints, reg2);
  2033. }
  2034. return 1;
  2035. #endif
  2036. } else {
  2037. /* TODO: enable interval splitting ??? */
  2038. /* register available for the first part of the interval */
  2039. if (1 || zend_jit_split_interval(current, pos, list, free) != SUCCESS) {
  2040. return 0;
  2041. }
  2042. current->reg = reg;
  2043. if (current->used_as_hint) {
  2044. ZEND_REGSET_INCL(*hints, reg);
  2045. }
  2046. return 1;
  2047. }
  2048. }
  2049. /* See "Optimized Interval Splitting in a Linear Scan Register Allocator",
  2050. Christian Wimmer VEE'05 (2005), Figure 5. Allocation with spilling.
  2051. and "Linear Scan Register Allocation on SSA Form", Christian Wimmer and
  2052. Michael Franz, CGO'10 (2010), Figure 6. */
  2053. static int zend_jit_allocate_blocked_reg(void)
  2054. {
  2055. /* TODO: ??? */
  2056. return 0;
  2057. }
  2058. /* See "Optimized Interval Splitting in a Linear Scan Register Allocator",
  2059. Christian Wimmer VEE'10 (2005), Figure 2. */
  2060. static zend_lifetime_interval* zend_jit_linear_scan(const zend_op_array *op_array, const zend_op **ssa_opcodes, zend_ssa *ssa, zend_lifetime_interval *list)
  2061. {
  2062. zend_lifetime_interval *unhandled, *active, *inactive, *handled, *free;
  2063. zend_lifetime_interval *current, **p, *q;
  2064. uint32_t position;
  2065. zend_regset available = ZEND_REGSET_UNION(ZEND_REGSET_GP, ZEND_REGSET_FP);
  2066. zend_regset hints = ZEND_REGSET_EMPTY;
  2067. unhandled = list;
  2068. /* active = inactive = handled = free = {} */
  2069. active = inactive = handled = free = NULL;
  2070. while (unhandled != NULL) {
  2071. current = unhandled;
  2072. unhandled = unhandled->list_next;
  2073. position = current->range.start;
  2074. p = &active;
  2075. while (*p) {
  2076. uint32_t end = zend_interval_end(*p);
  2077. q = *p;
  2078. if (end < position) {
  2079. /* move ival from active to handled */
  2080. ZEND_REGSET_INCL(available, q->reg);
  2081. *p = q->list_next;
  2082. q->list_next = handled;
  2083. handled = q;
  2084. } else if (!zend_interval_covers(q, position)) {
  2085. /* move ival from active to inactive */
  2086. ZEND_REGSET_INCL(available, q->reg);
  2087. *p = q->list_next;
  2088. q->list_next = inactive;
  2089. inactive = q;
  2090. } else {
  2091. p = &q->list_next;
  2092. }
  2093. }
  2094. p = &inactive;
  2095. while (*p) {
  2096. uint32_t end = zend_interval_end(*p);
  2097. q = *p;
  2098. if (end < position) {
  2099. /* move ival from inactive to handled */
  2100. *p = q->list_next;
  2101. q->list_next = handled;
  2102. handled = q;
  2103. } else if (zend_interval_covers(q, position)) {
  2104. /* move ival from inactive to active */
  2105. ZEND_REGSET_EXCL(available, q->reg);
  2106. *p = q->list_next;
  2107. q->list_next = active;
  2108. active = q;
  2109. } else {
  2110. p = &q->list_next;
  2111. }
  2112. }
  2113. if (zend_jit_try_allocate_free_reg(op_array, ssa_opcodes, ssa, current, available, &hints, active, inactive, &unhandled, &free) ||
  2114. zend_jit_allocate_blocked_reg()) {
  2115. ZEND_REGSET_EXCL(available, current->reg);
  2116. current->list_next = active;
  2117. active = current;
  2118. } else {
  2119. current->list_next = free;
  2120. free = current;
  2121. }
  2122. }
  2123. /* move active to handled */
  2124. while (active) {
  2125. current = active;
  2126. active = active->list_next;
  2127. current->list_next = handled;
  2128. handled = current;
  2129. }
  2130. /* move inactive to handled */
  2131. while (inactive) {
  2132. current = inactive;
  2133. inactive = inactive->list_next;
  2134. current->list_next = handled;
  2135. handled = current;
  2136. }
  2137. return handled;
  2138. }
  2139. static void zend_jit_dump_lifetime_interval(const zend_op_array *op_array, const zend_ssa *ssa, const zend_lifetime_interval *ival)
  2140. {
  2141. zend_life_range *range;
  2142. int var_num = ssa->vars[ival->ssa_var].var;
  2143. fprintf(stderr, "#%d.", ival->ssa_var);
  2144. zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : 0), var_num);
  2145. fprintf(stderr, ": %u-%u", ival->range.start, ival->range.end);
  2146. range = ival->range.next;
  2147. while (range) {
  2148. fprintf(stderr, ", %u-%u", range->start, range->end);
  2149. range = range->next;
  2150. }
  2151. if (ival->reg != ZREG_NONE) {
  2152. fprintf(stderr, " (%s)", zend_reg_name[ival->reg]);
  2153. }
  2154. if (ival->flags & ZREG_LAST_USE) {
  2155. fprintf(stderr, " last_use");
  2156. }
  2157. if (ival->flags & ZREG_LOAD) {
  2158. fprintf(stderr, " load");
  2159. }
  2160. if (ival->flags & ZREG_STORE) {
  2161. fprintf(stderr, " store");
  2162. }
  2163. if (ival->hint) {
  2164. fprintf(stderr, " hint");
  2165. if (ival->hint->ssa_var >= 0) {
  2166. var_num = ssa->vars[ival->hint->ssa_var].var;
  2167. fprintf(stderr, "=#%d.", ival->hint->ssa_var);
  2168. zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : 0), var_num);
  2169. }
  2170. if (ival->hint->reg != ZREG_NONE) {
  2171. fprintf(stderr, " (%s)", zend_reg_name[ival->hint->reg]);
  2172. }
  2173. }
  2174. fprintf(stderr, "\n");
  2175. }
  2176. static zend_lifetime_interval** zend_jit_allocate_registers(const zend_op_array *op_array, zend_ssa *ssa)
  2177. {
  2178. void *checkpoint;
  2179. int set_size, candidates_count, i;
  2180. zend_bitset candidates = NULL;
  2181. zend_lifetime_interval *list, *ival;
  2182. zend_lifetime_interval **intervals;
  2183. ALLOCA_FLAG(use_heap);
  2184. if (!ssa->var_info) {
  2185. return NULL;
  2186. }
  2187. /* Identify SSA variables suitable for register allocation */
  2188. set_size = zend_bitset_len(ssa->vars_count);
  2189. candidates = ZEND_BITSET_ALLOCA(set_size, use_heap);
  2190. if (!candidates) {
  2191. return NULL;
  2192. }
  2193. candidates_count = 0;
  2194. zend_bitset_clear(candidates, set_size);
  2195. for (i = 0; i < ssa->vars_count; i++) {
  2196. if (zend_jit_may_be_in_reg(op_array, ssa, i)) {
  2197. zend_bitset_incl(candidates, i);
  2198. candidates_count++;
  2199. }
  2200. }
  2201. if (!candidates_count) {
  2202. free_alloca(candidates, use_heap);
  2203. return NULL;
  2204. }
  2205. checkpoint = zend_arena_checkpoint(CG(arena));
  2206. /* Find life-time intervals */
  2207. if (zend_jit_compute_liveness(op_array, ssa, candidates, &list) != SUCCESS) {
  2208. goto failure;
  2209. }
  2210. if (list) {
  2211. /* Set ZREG_LAST_USE flags */
  2212. ival = list;
  2213. while (ival) {
  2214. zend_life_range *range = &ival->range;
  2215. while (range->next) {
  2216. range = range->next;
  2217. }
  2218. if (zend_ssa_is_last_use(op_array, ssa, ival->ssa_var, range->end)) {
  2219. ival->flags |= ZREG_LAST_USE;
  2220. }
  2221. ival = ival->list_next;
  2222. }
  2223. }
  2224. if (list) {
  2225. if (JIT_G(debug) & ZEND_JIT_DEBUG_REG_ALLOC) {
  2226. fprintf(stderr, "Live Ranges \"%s\"\n", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "[main]");
  2227. ival = list;
  2228. while (ival) {
  2229. zend_jit_dump_lifetime_interval(op_array, ssa, ival);
  2230. ival = ival->list_next;
  2231. }
  2232. fprintf(stderr, "\n");
  2233. }
  2234. /* Linear Scan Register Allocation */
  2235. list = zend_jit_linear_scan(op_array, NULL, ssa, list);
  2236. if (list) {
  2237. intervals = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_lifetime_interval*));
  2238. if (!intervals) {
  2239. goto failure;
  2240. }
  2241. ival = list;
  2242. while (ival != NULL) {
  2243. zend_lifetime_interval *next = ival->list_next;
  2244. ival->list_next = intervals[ival->ssa_var];
  2245. intervals[ival->ssa_var] = ival;
  2246. ival = next;
  2247. }
  2248. if (JIT_G(opt_flags) & ZEND_JIT_REG_ALLOC_GLOBAL) {
  2249. /* Naive SSA resolution */
  2250. for (i = 0; i < ssa->vars_count; i++) {
  2251. if (ssa->vars[i].definition_phi && !ssa->vars[i].no_val) {
  2252. zend_ssa_phi *phi = ssa->vars[i].definition_phi;
  2253. int k, src;
  2254. if (phi->pi >= 0) {
  2255. if (!ssa->vars[i].phi_use_chain
  2256. || ssa->vars[i].phi_use_chain->block != phi->block) {
  2257. src = phi->sources[0];
  2258. if (intervals[i]) {
  2259. if (!intervals[src]) {
  2260. intervals[i]->flags |= ZREG_LOAD;
  2261. } else if (intervals[i]->reg != intervals[src]->reg) {
  2262. intervals[i]->flags |= ZREG_LOAD;
  2263. intervals[src]->flags |= ZREG_STORE;
  2264. }
  2265. } else if (intervals[src]) {
  2266. intervals[src]->flags |= ZREG_STORE;
  2267. }
  2268. }
  2269. } else {
  2270. int need_move = 0;
  2271. for (k = 0; k < ssa->cfg.blocks[phi->block].predecessors_count; k++) {
  2272. src = phi->sources[k];
  2273. if (src >= 0) {
  2274. if (ssa->vars[src].definition_phi
  2275. && ssa->vars[src].definition_phi->pi >= 0
  2276. && phi->block == ssa->vars[src].definition_phi->block) {
  2277. /* Skip zero-length interval for Pi variable */
  2278. src = ssa->vars[src].definition_phi->sources[0];
  2279. }
  2280. if (intervals[i]) {
  2281. if (!intervals[src]) {
  2282. need_move = 1;
  2283. } else if (intervals[i]->reg != intervals[src]->reg) {
  2284. need_move = 1;
  2285. }
  2286. } else if (intervals[src]) {
  2287. need_move = 1;
  2288. }
  2289. }
  2290. }
  2291. if (need_move) {
  2292. if (intervals[i]) {
  2293. intervals[i]->flags |= ZREG_LOAD;
  2294. }
  2295. for (k = 0; k < ssa->cfg.blocks[phi->block].predecessors_count; k++) {
  2296. src = phi->sources[k];
  2297. if (src >= 0) {
  2298. if (ssa->vars[src].definition_phi
  2299. && ssa->vars[src].definition_phi->pi >= 0
  2300. && phi->block == ssa->vars[src].definition_phi->block) {
  2301. /* Skip zero-length interval for Pi variable */
  2302. src = ssa->vars[src].definition_phi->sources[0];
  2303. }
  2304. if (intervals[src]) {
  2305. intervals[src]->flags |= ZREG_STORE;
  2306. }
  2307. }
  2308. }
  2309. }
  2310. }
  2311. }
  2312. }
  2313. /* Remove useless register allocation */
  2314. for (i = 0; i < ssa->vars_count; i++) {
  2315. if (intervals[i] &&
  2316. ((intervals[i]->flags & ZREG_LOAD) ||
  2317. ((intervals[i]->flags & ZREG_STORE) && ssa->vars[i].definition >= 0)) &&
  2318. ssa->vars[i].use_chain < 0) {
  2319. bool may_remove = 1;
  2320. zend_ssa_phi *phi = ssa->vars[i].phi_use_chain;
  2321. while (phi) {
  2322. if (intervals[phi->ssa_var] &&
  2323. !(intervals[phi->ssa_var]->flags & ZREG_LOAD)) {
  2324. may_remove = 0;
  2325. break;
  2326. }
  2327. phi = zend_ssa_next_use_phi(ssa, i, phi);
  2328. }
  2329. if (may_remove) {
  2330. intervals[i] = NULL;
  2331. }
  2332. }
  2333. }
  2334. /* Remove intervals used once */
  2335. for (i = 0; i < ssa->vars_count; i++) {
  2336. if (intervals[i] &&
  2337. (intervals[i]->flags & ZREG_LOAD) &&
  2338. (intervals[i]->flags & ZREG_STORE) &&
  2339. (ssa->vars[i].use_chain < 0 ||
  2340. zend_ssa_next_use(ssa->ops, i, ssa->vars[i].use_chain) < 0)) {
  2341. bool may_remove = 1;
  2342. zend_ssa_phi *phi = ssa->vars[i].phi_use_chain;
  2343. while (phi) {
  2344. if (intervals[phi->ssa_var] &&
  2345. !(intervals[phi->ssa_var]->flags & ZREG_LOAD)) {
  2346. may_remove = 0;
  2347. break;
  2348. }
  2349. phi = zend_ssa_next_use_phi(ssa, i, phi);
  2350. }
  2351. if (may_remove) {
  2352. intervals[i] = NULL;
  2353. }
  2354. }
  2355. }
  2356. }
  2357. if (JIT_G(debug) & ZEND_JIT_DEBUG_REG_ALLOC) {
  2358. fprintf(stderr, "Allocated Live Ranges \"%s\"\n", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "[main]");
  2359. for (i = 0; i < ssa->vars_count; i++) {
  2360. ival = intervals[i];
  2361. while (ival) {
  2362. zend_jit_dump_lifetime_interval(op_array, ssa, ival);
  2363. ival = ival->list_next;
  2364. }
  2365. }
  2366. fprintf(stderr, "\n");
  2367. }
  2368. free_alloca(candidates, use_heap);
  2369. return intervals;
  2370. }
  2371. }
  2372. failure:
  2373. zend_arena_release(&CG(arena), checkpoint);
  2374. free_alloca(candidates, use_heap);
  2375. return NULL;
  2376. }
  2377. static bool zend_jit_next_is_send_result(const zend_op *opline)
  2378. {
  2379. if (opline->result_type == IS_TMP_VAR
  2380. && (opline+1)->opcode == ZEND_SEND_VAL
  2381. && (opline+1)->op1_type == IS_TMP_VAR
  2382. && (opline+1)->op2_type != IS_CONST
  2383. && (opline+1)->op1.var == opline->result.var) {
  2384. return 1;
  2385. }
  2386. return 0;
  2387. }
  2388. static bool zend_jit_supported_binary_op(zend_uchar op, uint32_t op1_info, uint32_t op2_info)
  2389. {
  2390. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  2391. return false;
  2392. }
  2393. switch (op) {
  2394. case ZEND_POW:
  2395. case ZEND_DIV:
  2396. // TODO: check for division by zero ???
  2397. return false;
  2398. case ZEND_ADD:
  2399. case ZEND_SUB:
  2400. case ZEND_MUL:
  2401. return (op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE))
  2402. && (op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE));
  2403. case ZEND_BW_OR:
  2404. case ZEND_BW_AND:
  2405. case ZEND_BW_XOR:
  2406. case ZEND_SL:
  2407. case ZEND_SR:
  2408. case ZEND_MOD:
  2409. return (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG);
  2410. case ZEND_CONCAT:
  2411. return (op1_info & MAY_BE_STRING) && (op2_info & MAY_BE_STRING);
  2412. EMPTY_SWITCH_DEFAULT_CASE()
  2413. }
  2414. }
  2415. static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op *rt_opline)
  2416. {
  2417. int b, i, end;
  2418. zend_op *opline;
  2419. dasm_State* dasm_state = NULL;
  2420. void *handler;
  2421. int call_level = 0;
  2422. void *checkpoint = NULL;
  2423. zend_lifetime_interval **ra = NULL;
  2424. bool is_terminated = 1; /* previous basic block is terminated by jump */
  2425. bool recv_emitted = 0; /* emitted at least one RECV opcode */
  2426. zend_uchar smart_branch_opcode;
  2427. uint32_t target_label, target_label2;
  2428. uint32_t op1_info, op1_def_info, op2_info, res_info, res_use_info;
  2429. zend_jit_addr op1_addr, op1_def_addr, op2_addr, op2_def_addr, res_addr;
  2430. zend_class_entry *ce;
  2431. bool ce_is_instanceof;
  2432. bool on_this;
  2433. if (JIT_G(bisect_limit)) {
  2434. jit_bisect_pos++;
  2435. if (jit_bisect_pos >= JIT_G(bisect_limit)) {
  2436. if (jit_bisect_pos == JIT_G(bisect_limit)) {
  2437. fprintf(stderr, "Not JITing %s%s%s in %s:%d and after due to jit_bisect_limit\n",
  2438. op_array->scope ? ZSTR_VAL(op_array->scope->name) : "",
  2439. op_array->scope ? "::" : "",
  2440. op_array->function_name ? ZSTR_VAL(op_array->function_name) : "{main}",
  2441. ZSTR_VAL(op_array->filename), op_array->line_start);
  2442. }
  2443. return FAILURE;
  2444. }
  2445. }
  2446. if (JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL)) {
  2447. checkpoint = zend_arena_checkpoint(CG(arena));
  2448. ra = zend_jit_allocate_registers(op_array, ssa);
  2449. }
  2450. /* mark hidden branch targets */
  2451. for (b = 0; b < ssa->cfg.blocks_count; b++) {
  2452. if (ssa->cfg.blocks[b].flags & ZEND_BB_REACHABLE &&
  2453. ssa->cfg.blocks[b].len > 1) {
  2454. opline = op_array->opcodes + ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len - 1;
  2455. if (opline->opcode == ZEND_DO_FCALL &&
  2456. (opline-1)->opcode == ZEND_NEW) {
  2457. ssa->cfg.blocks[ssa->cfg.blocks[b].successors[0]].flags |= ZEND_BB_TARGET;
  2458. }
  2459. }
  2460. }
  2461. dasm_init(&dasm_state, DASM_MAXSECTION);
  2462. dasm_setupglobal(&dasm_state, dasm_labels, zend_lb_MAX);
  2463. dasm_setup(&dasm_state, dasm_actions);
  2464. dasm_growpc(&dasm_state, ssa->cfg.blocks_count * 2 + 1);
  2465. zend_jit_align_func(&dasm_state);
  2466. for (b = 0; b < ssa->cfg.blocks_count; b++) {
  2467. if ((ssa->cfg.blocks[b].flags & ZEND_BB_REACHABLE) == 0) {
  2468. continue;
  2469. }
  2470. //#ifndef CONTEXT_THREADED_JIT
  2471. if (ssa->cfg.blocks[b].flags & ZEND_BB_ENTRY) {
  2472. if (ssa->cfg.blocks[b].flags & ZEND_BB_TARGET) {
  2473. /* pass */
  2474. } else if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE &&
  2475. ssa->cfg.blocks[b].len == 1 &&
  2476. (ssa->cfg.blocks[b].flags & ZEND_BB_EXIT) &&
  2477. op_array->opcodes[ssa->cfg.blocks[b].start].opcode != ZEND_JMP) {
  2478. /* don't generate code for BB with single opcode */
  2479. continue;
  2480. }
  2481. if (ssa->cfg.blocks[b].flags & ZEND_BB_FOLLOW) {
  2482. if (!is_terminated) {
  2483. zend_jit_jmp(&dasm_state, b);
  2484. }
  2485. }
  2486. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b);
  2487. zend_jit_prologue(&dasm_state);
  2488. } else
  2489. //#endif
  2490. if (ssa->cfg.blocks[b].flags & (ZEND_BB_START|ZEND_BB_RECV_ENTRY)) {
  2491. opline = op_array->opcodes + ssa->cfg.blocks[b].start;
  2492. if (ssa->cfg.flags & ZEND_CFG_RECV_ENTRY) {
  2493. if (opline->opcode == ZEND_RECV_INIT) {
  2494. if (opline == op_array->opcodes ||
  2495. (opline-1)->opcode != ZEND_RECV_INIT) {
  2496. if (recv_emitted) {
  2497. zend_jit_jmp(&dasm_state, b);
  2498. }
  2499. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b);
  2500. for (i = 1; (opline+i)->opcode == ZEND_RECV_INIT; i++) {
  2501. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b + i);
  2502. }
  2503. zend_jit_prologue(&dasm_state);
  2504. }
  2505. recv_emitted = 1;
  2506. } else if (opline->opcode == ZEND_RECV) {
  2507. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  2508. /* skip */
  2509. continue;
  2510. } else if (recv_emitted) {
  2511. zend_jit_jmp(&dasm_state, b);
  2512. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b);
  2513. zend_jit_prologue(&dasm_state);
  2514. } else {
  2515. zend_arg_info *arg_info;
  2516. if (opline->op1.num <= op_array->num_args) {
  2517. arg_info = &op_array->arg_info[opline->op1.num - 1];
  2518. } else if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
  2519. arg_info = &op_array->arg_info[op_array->num_args];
  2520. } else {
  2521. /* skip */
  2522. continue;
  2523. }
  2524. if (!ZEND_TYPE_IS_SET(arg_info->type)) {
  2525. /* skip */
  2526. continue;
  2527. }
  2528. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b);
  2529. zend_jit_prologue(&dasm_state);
  2530. recv_emitted = 1;
  2531. }
  2532. } else {
  2533. if (recv_emitted) {
  2534. zend_jit_jmp(&dasm_state, b);
  2535. } else if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE &&
  2536. ssa->cfg.blocks[b].len == 1 &&
  2537. (ssa->cfg.blocks[b].flags & ZEND_BB_EXIT)) {
  2538. /* don't generate code for BB with single opcode */
  2539. dasm_free(&dasm_state);
  2540. if (JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL)) {
  2541. zend_arena_release(&CG(arena), checkpoint);
  2542. }
  2543. return SUCCESS;
  2544. }
  2545. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b);
  2546. zend_jit_prologue(&dasm_state);
  2547. recv_emitted = 1;
  2548. }
  2549. } else if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE &&
  2550. ssa->cfg.blocks[b].len == 1 &&
  2551. (ssa->cfg.blocks[b].flags & ZEND_BB_EXIT)) {
  2552. /* don't generate code for BB with single opcode */
  2553. dasm_free(&dasm_state);
  2554. if (JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL)) {
  2555. zend_arena_release(&CG(arena), checkpoint);
  2556. }
  2557. return SUCCESS;
  2558. } else {
  2559. zend_jit_label(&dasm_state, ssa->cfg.blocks_count + b);
  2560. zend_jit_prologue(&dasm_state);
  2561. }
  2562. }
  2563. is_terminated = 0;
  2564. zend_jit_label(&dasm_state, b);
  2565. if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) {
  2566. if ((ssa->cfg.blocks[b].flags & ZEND_BB_FOLLOW)
  2567. && ssa->cfg.blocks[b].start != 0
  2568. && (op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_NOP
  2569. || op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_LONG
  2570. || op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_STRING
  2571. || op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_MATCH)) {
  2572. zend_jit_reset_last_valid_opline();
  2573. if (!zend_jit_set_ip(&dasm_state, op_array->opcodes + ssa->cfg.blocks[b].start)) {
  2574. goto jit_failure;
  2575. }
  2576. } else {
  2577. zend_jit_set_last_valid_opline(op_array->opcodes + ssa->cfg.blocks[b].start);
  2578. }
  2579. } else if (ssa->cfg.blocks[b].flags & ZEND_BB_TARGET) {
  2580. zend_jit_reset_last_valid_opline();
  2581. } else if (ssa->cfg.blocks[b].flags & (ZEND_BB_START|ZEND_BB_RECV_ENTRY|ZEND_BB_ENTRY)) {
  2582. zend_jit_set_last_valid_opline(op_array->opcodes + ssa->cfg.blocks[b].start);
  2583. }
  2584. if (ssa->cfg.blocks[b].flags & ZEND_BB_LOOP_HEADER) {
  2585. if (!zend_jit_check_timeout(&dasm_state, op_array->opcodes + ssa->cfg.blocks[b].start, NULL)) {
  2586. goto jit_failure;
  2587. }
  2588. }
  2589. if (!ssa->cfg.blocks[b].len) {
  2590. continue;
  2591. }
  2592. if ((JIT_G(opt_flags) & ZEND_JIT_REG_ALLOC_GLOBAL) && ra) {
  2593. zend_ssa_phi *phi = ssa->blocks[b].phis;
  2594. while (phi) {
  2595. zend_lifetime_interval *ival = ra[phi->ssa_var];
  2596. if (ival) {
  2597. if (ival->flags & ZREG_LOAD) {
  2598. ZEND_ASSERT(ival->reg != ZREG_NONE);
  2599. if (!zend_jit_load_var(&dasm_state, ssa->var_info[phi->ssa_var].type, ssa->vars[phi->ssa_var].var, ival->reg)) {
  2600. goto jit_failure;
  2601. }
  2602. } else if (ival->flags & ZREG_STORE) {
  2603. ZEND_ASSERT(ival->reg != ZREG_NONE);
  2604. if (!zend_jit_store_var(&dasm_state, ssa->var_info[phi->ssa_var].type, ssa->vars[phi->ssa_var].var, ival->reg, 1)) {
  2605. goto jit_failure;
  2606. }
  2607. }
  2608. }
  2609. phi = phi->next;
  2610. }
  2611. }
  2612. end = ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len - 1;
  2613. for (i = ssa->cfg.blocks[b].start; i <= end; i++) {
  2614. zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[i] : NULL;
  2615. opline = op_array->opcodes + i;
  2616. switch (opline->opcode) {
  2617. case ZEND_INIT_FCALL:
  2618. case ZEND_INIT_FCALL_BY_NAME:
  2619. case ZEND_INIT_NS_FCALL_BY_NAME:
  2620. case ZEND_INIT_METHOD_CALL:
  2621. case ZEND_INIT_DYNAMIC_CALL:
  2622. case ZEND_INIT_STATIC_METHOD_CALL:
  2623. case ZEND_INIT_USER_CALL:
  2624. case ZEND_NEW:
  2625. call_level++;
  2626. }
  2627. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
  2628. switch (opline->opcode) {
  2629. case ZEND_PRE_INC:
  2630. case ZEND_PRE_DEC:
  2631. case ZEND_POST_INC:
  2632. case ZEND_POST_DEC:
  2633. if (opline->op1_type != IS_CV) {
  2634. break;
  2635. }
  2636. op1_info = OP1_INFO();
  2637. if (!(op1_info & MAY_BE_LONG)) {
  2638. break;
  2639. }
  2640. if (opline->result_type != IS_UNUSED) {
  2641. res_use_info = -1;
  2642. if (opline->result_type == IS_CV
  2643. && ssa->vars
  2644. && ssa_op->result_use >= 0
  2645. && !ssa->vars[ssa_op->result_use].no_val) {
  2646. zend_jit_addr res_use_addr = RES_USE_REG_ADDR();
  2647. if (Z_MODE(res_use_addr) != IS_REG
  2648. || Z_LOAD(res_use_addr)
  2649. || Z_STORE(res_use_addr)) {
  2650. res_use_info = RES_USE_INFO();
  2651. }
  2652. }
  2653. res_info = RES_INFO();
  2654. res_addr = RES_REG_ADDR();
  2655. } else {
  2656. res_use_info = -1;
  2657. res_info = -1;
  2658. res_addr = 0;
  2659. }
  2660. op1_def_info = OP1_DEF_INFO();
  2661. if (!zend_jit_inc_dec(&dasm_state, opline,
  2662. op1_info, OP1_REG_ADDR(),
  2663. op1_def_info, OP1_DEF_REG_ADDR(),
  2664. res_use_info, res_info,
  2665. res_addr,
  2666. (op1_info & MAY_BE_LONG) && (op1_def_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
  2667. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2668. goto jit_failure;
  2669. }
  2670. goto done;
  2671. case ZEND_BW_OR:
  2672. case ZEND_BW_AND:
  2673. case ZEND_BW_XOR:
  2674. case ZEND_SL:
  2675. case ZEND_SR:
  2676. case ZEND_MOD:
  2677. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2678. break;
  2679. }
  2680. op1_info = OP1_INFO();
  2681. op2_info = OP2_INFO();
  2682. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  2683. break;
  2684. }
  2685. if (!(op1_info & MAY_BE_LONG)
  2686. || !(op2_info & MAY_BE_LONG)) {
  2687. break;
  2688. }
  2689. res_addr = RES_REG_ADDR();
  2690. if (Z_MODE(res_addr) != IS_REG
  2691. && (i + 1) <= end
  2692. && zend_jit_next_is_send_result(opline)) {
  2693. i++;
  2694. res_use_info = -1;
  2695. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  2696. if (!zend_jit_reuse_ip(&dasm_state)) {
  2697. goto jit_failure;
  2698. }
  2699. } else {
  2700. res_use_info = -1;
  2701. if (opline->result_type == IS_CV
  2702. && ssa->vars
  2703. && ssa_op->result_use >= 0
  2704. && !ssa->vars[ssa_op->result_use].no_val) {
  2705. zend_jit_addr res_use_addr = RES_USE_REG_ADDR();
  2706. if (Z_MODE(res_use_addr) != IS_REG
  2707. || Z_LOAD(res_use_addr)
  2708. || Z_STORE(res_use_addr)) {
  2709. res_use_info = RES_USE_INFO();
  2710. }
  2711. }
  2712. }
  2713. if (!zend_jit_long_math(&dasm_state, opline,
  2714. op1_info, OP1_RANGE(), OP1_REG_ADDR(),
  2715. op2_info, OP2_RANGE(), OP2_REG_ADDR(),
  2716. res_use_info, RES_INFO(), res_addr,
  2717. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2718. goto jit_failure;
  2719. }
  2720. goto done;
  2721. case ZEND_ADD:
  2722. case ZEND_SUB:
  2723. case ZEND_MUL:
  2724. // case ZEND_DIV: // TODO: check for division by zero ???
  2725. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2726. break;
  2727. }
  2728. op1_info = OP1_INFO();
  2729. op2_info = OP2_INFO();
  2730. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  2731. break;
  2732. }
  2733. if (opline->opcode == ZEND_ADD &&
  2734. (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
  2735. (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
  2736. /* pass */
  2737. } else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
  2738. !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
  2739. break;
  2740. }
  2741. res_addr = RES_REG_ADDR();
  2742. if (Z_MODE(res_addr) != IS_REG
  2743. && (i + 1) <= end
  2744. && zend_jit_next_is_send_result(opline)) {
  2745. i++;
  2746. res_use_info = -1;
  2747. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  2748. if (!zend_jit_reuse_ip(&dasm_state)) {
  2749. goto jit_failure;
  2750. }
  2751. } else {
  2752. res_use_info = -1;
  2753. if (opline->result_type == IS_CV
  2754. && ssa->vars
  2755. && ssa_op->result_use >= 0
  2756. && !ssa->vars[ssa_op->result_use].no_val) {
  2757. zend_jit_addr res_use_addr = RES_USE_REG_ADDR();
  2758. if (Z_MODE(res_use_addr) != IS_REG
  2759. || Z_LOAD(res_use_addr)
  2760. || Z_STORE(res_use_addr)) {
  2761. res_use_info = RES_USE_INFO();
  2762. }
  2763. }
  2764. }
  2765. res_info = RES_INFO();
  2766. if (opline->opcode == ZEND_ADD &&
  2767. (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
  2768. (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
  2769. if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, OP1_REG_ADDR(), op2_info, OP2_REG_ADDR(), res_addr)) {
  2770. goto jit_failure;
  2771. }
  2772. } else {
  2773. if (!zend_jit_math(&dasm_state, opline,
  2774. op1_info, OP1_REG_ADDR(),
  2775. op2_info, OP2_REG_ADDR(),
  2776. res_use_info, res_info, res_addr,
  2777. (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
  2778. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2779. goto jit_failure;
  2780. }
  2781. }
  2782. goto done;
  2783. case ZEND_CONCAT:
  2784. case ZEND_FAST_CONCAT:
  2785. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2786. break;
  2787. }
  2788. op1_info = OP1_INFO();
  2789. op2_info = OP2_INFO();
  2790. if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
  2791. break;
  2792. }
  2793. if (!(op1_info & MAY_BE_STRING) ||
  2794. !(op2_info & MAY_BE_STRING)) {
  2795. break;
  2796. }
  2797. res_addr = RES_REG_ADDR();
  2798. if ((i + 1) <= end
  2799. && zend_jit_next_is_send_result(opline)) {
  2800. i++;
  2801. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  2802. if (!zend_jit_reuse_ip(&dasm_state)) {
  2803. goto jit_failure;
  2804. }
  2805. }
  2806. if (!zend_jit_concat(&dasm_state, opline,
  2807. op1_info, op2_info, res_addr,
  2808. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2809. goto jit_failure;
  2810. }
  2811. goto done;
  2812. case ZEND_ASSIGN_OP:
  2813. if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
  2814. break;
  2815. }
  2816. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2817. break;
  2818. }
  2819. op1_info = OP1_INFO();
  2820. op2_info = OP2_INFO();
  2821. if (!zend_jit_supported_binary_op(
  2822. opline->extended_value, op1_info, op2_info)) {
  2823. break;
  2824. }
  2825. op1_def_info = OP1_DEF_INFO();
  2826. if (!zend_jit_assign_op(&dasm_state, opline,
  2827. op1_info, op1_def_info, OP1_RANGE(),
  2828. op2_info, OP2_RANGE(),
  2829. (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (op1_def_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
  2830. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2831. goto jit_failure;
  2832. }
  2833. goto done;
  2834. case ZEND_ASSIGN_DIM_OP:
  2835. if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
  2836. break;
  2837. }
  2838. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2839. break;
  2840. }
  2841. if (!zend_jit_supported_binary_op(
  2842. opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
  2843. break;
  2844. }
  2845. if (!zend_jit_assign_dim_op(&dasm_state, opline,
  2846. OP1_INFO(), OP1_DEF_INFO(), OP1_REG_ADDR(), OP2_INFO(),
  2847. OP1_DATA_INFO(), OP1_DATA_RANGE(), IS_UNKNOWN,
  2848. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2849. goto jit_failure;
  2850. }
  2851. goto done;
  2852. case ZEND_ASSIGN_DIM:
  2853. if (opline->op1_type != IS_CV) {
  2854. break;
  2855. }
  2856. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2857. break;
  2858. }
  2859. if (!zend_jit_assign_dim(&dasm_state, opline,
  2860. OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), OP1_DATA_INFO(), IS_UNKNOWN,
  2861. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2862. goto jit_failure;
  2863. }
  2864. goto done;
  2865. case ZEND_PRE_INC_OBJ:
  2866. case ZEND_PRE_DEC_OBJ:
  2867. case ZEND_POST_INC_OBJ:
  2868. case ZEND_POST_DEC_OBJ:
  2869. if (opline->op2_type != IS_CONST
  2870. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  2871. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  2872. break;
  2873. }
  2874. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2875. break;
  2876. }
  2877. ce = NULL;
  2878. ce_is_instanceof = 0;
  2879. on_this = 0;
  2880. if (opline->op1_type == IS_UNUSED) {
  2881. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  2882. ce = op_array->scope;
  2883. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  2884. op1_addr = 0;
  2885. on_this = 1;
  2886. } else {
  2887. op1_info = OP1_INFO();
  2888. if (!(op1_info & MAY_BE_OBJECT)) {
  2889. break;
  2890. }
  2891. op1_addr = OP1_REG_ADDR();
  2892. if (ssa->var_info && ssa->ops) {
  2893. zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
  2894. if (ssa_op->op1_use >= 0) {
  2895. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  2896. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  2897. ce = op1_ssa->ce;
  2898. ce_is_instanceof = op1_ssa->is_instanceof;
  2899. }
  2900. }
  2901. }
  2902. }
  2903. if (!zend_jit_incdec_obj(&dasm_state, opline, op_array, ssa, ssa_op,
  2904. op1_info, op1_addr,
  2905. 0, ce, ce_is_instanceof, on_this, 0, NULL, IS_UNKNOWN)) {
  2906. goto jit_failure;
  2907. }
  2908. goto done;
  2909. case ZEND_ASSIGN_OBJ_OP:
  2910. if (opline->result_type != IS_UNUSED) {
  2911. break;
  2912. }
  2913. if (opline->op2_type != IS_CONST
  2914. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  2915. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  2916. break;
  2917. }
  2918. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2919. break;
  2920. }
  2921. if (!zend_jit_supported_binary_op(
  2922. opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
  2923. break;
  2924. }
  2925. ce = NULL;
  2926. ce_is_instanceof = 0;
  2927. on_this = 0;
  2928. if (opline->op1_type == IS_UNUSED) {
  2929. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  2930. ce = op_array->scope;
  2931. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  2932. op1_addr = 0;
  2933. on_this = 1;
  2934. } else {
  2935. op1_info = OP1_INFO();
  2936. if (!(op1_info & MAY_BE_OBJECT)) {
  2937. break;
  2938. }
  2939. op1_addr = OP1_REG_ADDR();
  2940. if (ssa->var_info && ssa->ops) {
  2941. zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
  2942. if (ssa_op->op1_use >= 0) {
  2943. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  2944. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  2945. ce = op1_ssa->ce;
  2946. ce_is_instanceof = op1_ssa->is_instanceof;
  2947. }
  2948. }
  2949. }
  2950. }
  2951. if (!zend_jit_assign_obj_op(&dasm_state, opline, op_array, ssa, ssa_op,
  2952. op1_info, op1_addr, OP1_DATA_INFO(), OP1_DATA_RANGE(),
  2953. 0, ce, ce_is_instanceof, on_this, 0, NULL, IS_UNKNOWN)) {
  2954. goto jit_failure;
  2955. }
  2956. goto done;
  2957. case ZEND_ASSIGN_OBJ:
  2958. if (opline->op2_type != IS_CONST
  2959. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  2960. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  2961. break;
  2962. }
  2963. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  2964. break;
  2965. }
  2966. ce = NULL;
  2967. ce_is_instanceof = 0;
  2968. on_this = 0;
  2969. if (opline->op1_type == IS_UNUSED) {
  2970. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  2971. ce = op_array->scope;
  2972. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  2973. op1_addr = 0;
  2974. on_this = 1;
  2975. } else {
  2976. op1_info = OP1_INFO();
  2977. if (!(op1_info & MAY_BE_OBJECT)) {
  2978. break;
  2979. }
  2980. op1_addr = OP1_REG_ADDR();
  2981. if (ssa->var_info && ssa->ops) {
  2982. zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
  2983. if (ssa_op->op1_use >= 0) {
  2984. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  2985. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  2986. ce = op1_ssa->ce;
  2987. ce_is_instanceof = op1_ssa->is_instanceof;
  2988. }
  2989. }
  2990. }
  2991. }
  2992. if (!zend_jit_assign_obj(&dasm_state, opline, op_array, ssa, ssa_op,
  2993. op1_info, op1_addr, OP1_DATA_INFO(),
  2994. 0, ce, ce_is_instanceof, on_this, 0, NULL, IS_UNKNOWN,
  2995. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  2996. goto jit_failure;
  2997. }
  2998. goto done;
  2999. case ZEND_ASSIGN:
  3000. if (opline->op1_type != IS_CV) {
  3001. break;
  3002. }
  3003. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  3004. break;
  3005. }
  3006. op2_addr = OP2_REG_ADDR();
  3007. if (ra
  3008. && ssa->ops[opline - op_array->opcodes].op2_def >= 0
  3009. && !ssa->vars[ssa->ops[opline - op_array->opcodes].op2_def].no_val) {
  3010. op2_def_addr = OP2_DEF_REG_ADDR();
  3011. } else {
  3012. op2_def_addr = op2_addr;
  3013. }
  3014. op1_info = OP1_INFO();
  3015. if (ra && ssa->vars[ssa_op->op1_use].no_val) {
  3016. op1_info |= MAY_BE_UNDEF; // requres type assignment
  3017. }
  3018. if (opline->result_type == IS_UNUSED) {
  3019. res_addr = 0;
  3020. res_info = -1;
  3021. } else {
  3022. res_addr = RES_REG_ADDR();
  3023. res_info = RES_INFO();
  3024. if (Z_MODE(res_addr) != IS_REG
  3025. && (i + 1) <= end
  3026. && zend_jit_next_is_send_result(opline)
  3027. && (!(op1_info & MAY_HAVE_DTOR) || !(op1_info & MAY_BE_RC1))) {
  3028. i++;
  3029. res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
  3030. if (!zend_jit_reuse_ip(&dasm_state)) {
  3031. goto jit_failure;
  3032. }
  3033. }
  3034. }
  3035. if (!zend_jit_assign(&dasm_state, opline,
  3036. op1_info, OP1_REG_ADDR(),
  3037. OP1_DEF_INFO(), OP1_DEF_REG_ADDR(),
  3038. OP2_INFO(), op2_addr, op2_def_addr,
  3039. res_info, res_addr,
  3040. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3041. goto jit_failure;
  3042. }
  3043. goto done;
  3044. case ZEND_QM_ASSIGN:
  3045. op1_addr = OP1_REG_ADDR();
  3046. if (ra
  3047. && ssa->ops[opline - op_array->opcodes].op1_def >= 0
  3048. && !ssa->vars[ssa->ops[opline - op_array->opcodes].op1_def].no_val) {
  3049. op1_def_addr = OP1_DEF_REG_ADDR();
  3050. } else {
  3051. op1_def_addr = op1_addr;
  3052. }
  3053. if (!zend_jit_qm_assign(&dasm_state, opline,
  3054. OP1_INFO(), op1_addr, op1_def_addr,
  3055. -1, RES_INFO(), RES_REG_ADDR())) {
  3056. goto jit_failure;
  3057. }
  3058. goto done;
  3059. case ZEND_INIT_FCALL:
  3060. case ZEND_INIT_FCALL_BY_NAME:
  3061. case ZEND_INIT_NS_FCALL_BY_NAME:
  3062. if (!zend_jit_init_fcall(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level, NULL, 0)) {
  3063. goto jit_failure;
  3064. }
  3065. goto done;
  3066. case ZEND_SEND_VAL:
  3067. case ZEND_SEND_VAL_EX:
  3068. if (opline->op2_type == IS_CONST) {
  3069. /* Named parameters not supported in JIT (yet) */
  3070. break;
  3071. }
  3072. if (opline->opcode == ZEND_SEND_VAL_EX
  3073. && opline->op2.num > MAX_ARG_FLAG_NUM) {
  3074. break;
  3075. }
  3076. if (!zend_jit_send_val(&dasm_state, opline,
  3077. OP1_INFO(), OP1_REG_ADDR())) {
  3078. goto jit_failure;
  3079. }
  3080. goto done;
  3081. case ZEND_SEND_REF:
  3082. if (opline->op2_type == IS_CONST) {
  3083. /* Named parameters not supported in JIT (yet) */
  3084. break;
  3085. }
  3086. if (!zend_jit_send_ref(&dasm_state, opline, op_array,
  3087. OP1_INFO(), 0)) {
  3088. goto jit_failure;
  3089. }
  3090. goto done;
  3091. case ZEND_SEND_VAR:
  3092. case ZEND_SEND_VAR_EX:
  3093. case ZEND_SEND_VAR_NO_REF:
  3094. case ZEND_SEND_VAR_NO_REF_EX:
  3095. case ZEND_SEND_FUNC_ARG:
  3096. if (opline->op2_type == IS_CONST) {
  3097. /* Named parameters not supported in JIT (yet) */
  3098. break;
  3099. }
  3100. if ((opline->opcode == ZEND_SEND_VAR_EX
  3101. || opline->opcode == ZEND_SEND_VAR_NO_REF_EX)
  3102. && opline->op2.num > MAX_ARG_FLAG_NUM) {
  3103. break;
  3104. }
  3105. op1_addr = OP1_REG_ADDR();
  3106. if (ra
  3107. && ssa->ops[opline - op_array->opcodes].op1_def >= 0
  3108. && !ssa->vars[ssa->ops[opline - op_array->opcodes].op1_def].no_val) {
  3109. op1_def_addr = OP1_DEF_REG_ADDR();
  3110. } else {
  3111. op1_def_addr = op1_addr;
  3112. }
  3113. if (!zend_jit_send_var(&dasm_state, opline, op_array,
  3114. OP1_INFO(), op1_addr, op1_def_addr)) {
  3115. goto jit_failure;
  3116. }
  3117. goto done;
  3118. case ZEND_CHECK_FUNC_ARG:
  3119. if (opline->op2_type == IS_CONST) {
  3120. /* Named parameters not supported in JIT (yet) */
  3121. break;
  3122. }
  3123. if (opline->op2.num > MAX_ARG_FLAG_NUM) {
  3124. break;
  3125. }
  3126. if (!zend_jit_check_func_arg(&dasm_state, opline)) {
  3127. goto jit_failure;
  3128. }
  3129. goto done;
  3130. case ZEND_CHECK_UNDEF_ARGS:
  3131. if (!zend_jit_check_undef_args(&dasm_state, opline)) {
  3132. goto jit_failure;
  3133. }
  3134. goto done;
  3135. case ZEND_DO_UCALL:
  3136. is_terminated = 1;
  3137. ZEND_FALLTHROUGH;
  3138. case ZEND_DO_ICALL:
  3139. case ZEND_DO_FCALL_BY_NAME:
  3140. case ZEND_DO_FCALL:
  3141. if (!zend_jit_do_fcall(&dasm_state, opline, op_array, ssa, call_level, b + 1, NULL)) {
  3142. goto jit_failure;
  3143. }
  3144. goto done;
  3145. case ZEND_IS_EQUAL:
  3146. case ZEND_IS_NOT_EQUAL:
  3147. case ZEND_IS_SMALLER:
  3148. case ZEND_IS_SMALLER_OR_EQUAL:
  3149. case ZEND_CASE: {
  3150. res_addr = RES_REG_ADDR();
  3151. if ((opline->result_type & IS_TMP_VAR)
  3152. && (i + 1) <= end
  3153. && ((opline+1)->opcode == ZEND_JMPZ
  3154. || (opline+1)->opcode == ZEND_JMPNZ
  3155. || (opline+1)->opcode == ZEND_JMPZ_EX
  3156. || (opline+1)->opcode == ZEND_JMPNZ_EX
  3157. || (opline+1)->opcode == ZEND_JMPZNZ)
  3158. && (opline+1)->op1_type == IS_TMP_VAR
  3159. && (opline+1)->op1.var == opline->result.var) {
  3160. i++;
  3161. smart_branch_opcode = (opline+1)->opcode;
  3162. target_label = ssa->cfg.blocks[b].successors[0];
  3163. target_label2 = ssa->cfg.blocks[b].successors[1];
  3164. /* For EX variant write into the result of EX opcode. */
  3165. if ((opline+1)->opcode == ZEND_JMPZ_EX
  3166. || (opline+1)->opcode == ZEND_JMPNZ_EX) {
  3167. res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
  3168. }
  3169. } else {
  3170. smart_branch_opcode = 0;
  3171. target_label = target_label2 = (uint32_t)-1;
  3172. }
  3173. if (!zend_jit_cmp(&dasm_state, opline,
  3174. OP1_INFO(), OP1_RANGE(), OP1_REG_ADDR(),
  3175. OP2_INFO(), OP2_RANGE(), OP2_REG_ADDR(),
  3176. res_addr,
  3177. zend_may_throw(opline, ssa_op, op_array, ssa),
  3178. smart_branch_opcode, target_label, target_label2,
  3179. NULL, 0)) {
  3180. goto jit_failure;
  3181. }
  3182. goto done;
  3183. }
  3184. case ZEND_IS_IDENTICAL:
  3185. case ZEND_IS_NOT_IDENTICAL:
  3186. case ZEND_CASE_STRICT:
  3187. if ((opline->result_type & IS_TMP_VAR)
  3188. && (i + 1) <= end
  3189. && ((opline+1)->opcode == ZEND_JMPZ
  3190. || (opline+1)->opcode == ZEND_JMPNZ
  3191. || (opline+1)->opcode == ZEND_JMPZNZ)
  3192. && (opline+1)->op1_type == IS_TMP_VAR
  3193. && (opline+1)->op1.var == opline->result.var) {
  3194. i++;
  3195. smart_branch_opcode = (opline+1)->opcode;
  3196. target_label = ssa->cfg.blocks[b].successors[0];
  3197. target_label2 = ssa->cfg.blocks[b].successors[1];
  3198. } else {
  3199. smart_branch_opcode = 0;
  3200. target_label = target_label2 = (uint32_t)-1;
  3201. }
  3202. if (!zend_jit_identical(&dasm_state, opline,
  3203. OP1_INFO(), OP1_RANGE(), OP1_REG_ADDR(),
  3204. OP2_INFO(), OP2_RANGE(), OP2_REG_ADDR(),
  3205. RES_REG_ADDR(),
  3206. zend_may_throw(opline, ssa_op, op_array, ssa),
  3207. smart_branch_opcode, target_label, target_label2,
  3208. NULL, 0)) {
  3209. goto jit_failure;
  3210. }
  3211. goto done;
  3212. case ZEND_DEFINED:
  3213. if ((opline->result_type & IS_TMP_VAR)
  3214. && (i + 1) <= end
  3215. && ((opline+1)->opcode == ZEND_JMPZ
  3216. || (opline+1)->opcode == ZEND_JMPNZ
  3217. || (opline+1)->opcode == ZEND_JMPZNZ)
  3218. && (opline+1)->op1_type == IS_TMP_VAR
  3219. && (opline+1)->op1.var == opline->result.var) {
  3220. i++;
  3221. smart_branch_opcode = (opline+1)->opcode;
  3222. target_label = ssa->cfg.blocks[b].successors[0];
  3223. target_label2 = ssa->cfg.blocks[b].successors[1];
  3224. } else {
  3225. smart_branch_opcode = 0;
  3226. target_label = target_label2 = (uint32_t)-1;
  3227. }
  3228. if (!zend_jit_defined(&dasm_state, opline, smart_branch_opcode, target_label, target_label2, NULL)) {
  3229. goto jit_failure;
  3230. }
  3231. goto done;
  3232. case ZEND_TYPE_CHECK:
  3233. if (opline->extended_value == MAY_BE_RESOURCE) {
  3234. // TODO: support for is_resource() ???
  3235. break;
  3236. }
  3237. if ((opline->result_type & IS_TMP_VAR)
  3238. && (i + 1) <= end
  3239. && ((opline+1)->opcode == ZEND_JMPZ
  3240. || (opline+1)->opcode == ZEND_JMPNZ
  3241. || (opline+1)->opcode == ZEND_JMPZNZ)
  3242. && (opline+1)->op1_type == IS_TMP_VAR
  3243. && (opline+1)->op1.var == opline->result.var) {
  3244. i++;
  3245. smart_branch_opcode = (opline+1)->opcode;
  3246. target_label = ssa->cfg.blocks[b].successors[0];
  3247. target_label2 = ssa->cfg.blocks[b].successors[1];
  3248. } else {
  3249. smart_branch_opcode = 0;
  3250. target_label = target_label2 = (uint32_t)-1;
  3251. }
  3252. if (!zend_jit_type_check(&dasm_state, opline, OP1_INFO(), smart_branch_opcode, target_label, target_label2, NULL)) {
  3253. goto jit_failure;
  3254. }
  3255. goto done;
  3256. case ZEND_RETURN:
  3257. op1_info = OP1_INFO();
  3258. if ((PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info))
  3259. || op_array->type == ZEND_EVAL_CODE
  3260. // TODO: support for top-level code
  3261. || !op_array->function_name
  3262. // TODO: support for IS_UNDEF ???
  3263. || (op1_info & MAY_BE_UNDEF)) {
  3264. if (!zend_jit_tail_handler(&dasm_state, opline)) {
  3265. goto jit_failure;
  3266. }
  3267. } else {
  3268. int j;
  3269. bool left_frame = 0;
  3270. if (!zend_jit_return(&dasm_state, opline, op_array,
  3271. op1_info, OP1_REG_ADDR())) {
  3272. goto jit_failure;
  3273. }
  3274. if (jit_return_label >= 0) {
  3275. if (!zend_jit_jmp(&dasm_state, jit_return_label)) {
  3276. goto jit_failure;
  3277. }
  3278. goto done;
  3279. }
  3280. jit_return_label = ssa->cfg.blocks_count * 2;
  3281. if (!zend_jit_label(&dasm_state, jit_return_label)) {
  3282. goto jit_failure;
  3283. }
  3284. if (op_array->last_var > 100) {
  3285. /* To many CVs to unroll */
  3286. if (!zend_jit_free_cvs(&dasm_state)) {
  3287. goto jit_failure;
  3288. }
  3289. left_frame = 1;
  3290. }
  3291. if (!left_frame) {
  3292. for (j = 0 ; j < op_array->last_var; j++) {
  3293. uint32_t info = zend_ssa_cv_info(op_array, ssa, j);
  3294. if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
  3295. if (!left_frame) {
  3296. left_frame = 1;
  3297. if (!zend_jit_leave_frame(&dasm_state)) {
  3298. goto jit_failure;
  3299. }
  3300. }
  3301. if (!zend_jit_free_cv(&dasm_state, info, j)) {
  3302. goto jit_failure;
  3303. }
  3304. }
  3305. }
  3306. }
  3307. if (!zend_jit_leave_func(&dasm_state, op_array, opline, op1_info, left_frame,
  3308. NULL, NULL, (ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0, 1)) {
  3309. goto jit_failure;
  3310. }
  3311. }
  3312. goto done;
  3313. case ZEND_BOOL:
  3314. case ZEND_BOOL_NOT:
  3315. if (!zend_jit_bool_jmpznz(&dasm_state, opline,
  3316. OP1_INFO(), OP1_REG_ADDR(), RES_REG_ADDR(),
  3317. -1, -1,
  3318. zend_may_throw(opline, ssa_op, op_array, ssa),
  3319. opline->opcode, NULL)) {
  3320. goto jit_failure;
  3321. }
  3322. goto done;
  3323. case ZEND_JMPZ:
  3324. case ZEND_JMPNZ:
  3325. if (opline > op_array->opcodes + ssa->cfg.blocks[b].start &&
  3326. ((opline-1)->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  3327. /* smart branch */
  3328. if (!zend_jit_cond_jmp(&dasm_state, opline + 1, ssa->cfg.blocks[b].successors[0])) {
  3329. goto jit_failure;
  3330. }
  3331. goto done;
  3332. }
  3333. ZEND_FALLTHROUGH;
  3334. case ZEND_JMPZNZ:
  3335. case ZEND_JMPZ_EX:
  3336. case ZEND_JMPNZ_EX:
  3337. if (opline->result_type == IS_UNDEF) {
  3338. res_addr = 0;
  3339. } else {
  3340. res_addr = RES_REG_ADDR();
  3341. }
  3342. if (!zend_jit_bool_jmpznz(&dasm_state, opline,
  3343. OP1_INFO(), OP1_REG_ADDR(), res_addr,
  3344. ssa->cfg.blocks[b].successors[0], ssa->cfg.blocks[b].successors[1],
  3345. zend_may_throw(opline, ssa_op, op_array, ssa),
  3346. opline->opcode, NULL)) {
  3347. goto jit_failure;
  3348. }
  3349. goto done;
  3350. case ZEND_ISSET_ISEMPTY_CV:
  3351. if ((opline->extended_value & ZEND_ISEMPTY)) {
  3352. // TODO: support for empty() ???
  3353. break;
  3354. }
  3355. if ((opline->result_type & IS_TMP_VAR)
  3356. && (i + 1) <= end
  3357. && ((opline+1)->opcode == ZEND_JMPZ
  3358. || (opline+1)->opcode == ZEND_JMPNZ
  3359. || (opline+1)->opcode == ZEND_JMPZNZ)
  3360. && (opline+1)->op1_type == IS_TMP_VAR
  3361. && (opline+1)->op1.var == opline->result.var) {
  3362. i++;
  3363. smart_branch_opcode = (opline+1)->opcode;
  3364. target_label = ssa->cfg.blocks[b].successors[0];
  3365. target_label2 = ssa->cfg.blocks[b].successors[1];
  3366. } else {
  3367. smart_branch_opcode = 0;
  3368. target_label = target_label2 = (uint32_t)-1;
  3369. }
  3370. if (!zend_jit_isset_isempty_cv(&dasm_state, opline,
  3371. OP1_INFO(), OP1_REG_ADDR(),
  3372. smart_branch_opcode, target_label, target_label2,
  3373. NULL)) {
  3374. goto jit_failure;
  3375. }
  3376. goto done;
  3377. case ZEND_IN_ARRAY:
  3378. if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
  3379. break;
  3380. }
  3381. op1_info = OP1_INFO();
  3382. if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_STRING) {
  3383. break;
  3384. }
  3385. if ((opline->result_type & IS_TMP_VAR)
  3386. && (i + 1) <= end
  3387. && ((opline+1)->opcode == ZEND_JMPZ
  3388. || (opline+1)->opcode == ZEND_JMPNZ
  3389. || (opline+1)->opcode == ZEND_JMPZNZ)
  3390. && (opline+1)->op1_type == IS_TMP_VAR
  3391. && (opline+1)->op1.var == opline->result.var) {
  3392. i++;
  3393. smart_branch_opcode = (opline+1)->opcode;
  3394. target_label = ssa->cfg.blocks[b].successors[0];
  3395. target_label2 = ssa->cfg.blocks[b].successors[1];
  3396. } else {
  3397. smart_branch_opcode = 0;
  3398. target_label = target_label2 = (uint32_t)-1;
  3399. }
  3400. if (!zend_jit_in_array(&dasm_state, opline,
  3401. op1_info, OP1_REG_ADDR(),
  3402. smart_branch_opcode, target_label, target_label2,
  3403. NULL)) {
  3404. goto jit_failure;
  3405. }
  3406. goto done;
  3407. case ZEND_FETCH_DIM_R:
  3408. case ZEND_FETCH_DIM_IS:
  3409. case ZEND_FETCH_LIST_R:
  3410. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  3411. break;
  3412. }
  3413. if (!zend_jit_fetch_dim_read(&dasm_state, opline, ssa, ssa_op,
  3414. OP1_INFO(), OP1_REG_ADDR(), 0,
  3415. OP2_INFO(), RES_INFO(), RES_REG_ADDR(), IS_UNKNOWN)) {
  3416. goto jit_failure;
  3417. }
  3418. goto done;
  3419. case ZEND_FETCH_DIM_W:
  3420. case ZEND_FETCH_DIM_RW:
  3421. // case ZEND_FETCH_DIM_UNSET:
  3422. case ZEND_FETCH_LIST_W:
  3423. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  3424. break;
  3425. }
  3426. if (opline->op1_type != IS_CV) {
  3427. break;
  3428. }
  3429. if (!zend_jit_fetch_dim(&dasm_state, opline,
  3430. OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_REG_ADDR(), IS_UNKNOWN)) {
  3431. goto jit_failure;
  3432. }
  3433. goto done;
  3434. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  3435. if ((opline->extended_value & ZEND_ISEMPTY)) {
  3436. // TODO: support for empty() ???
  3437. break;
  3438. }
  3439. if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
  3440. break;
  3441. }
  3442. if ((opline->result_type & IS_TMP_VAR)
  3443. && (i + 1) <= end
  3444. && ((opline+1)->opcode == ZEND_JMPZ
  3445. || (opline+1)->opcode == ZEND_JMPNZ
  3446. || (opline+1)->opcode == ZEND_JMPZNZ)
  3447. && (opline+1)->op1_type == IS_TMP_VAR
  3448. && (opline+1)->op1.var == opline->result.var) {
  3449. i++;
  3450. smart_branch_opcode = (opline+1)->opcode;
  3451. target_label = ssa->cfg.blocks[b].successors[0];
  3452. target_label2 = ssa->cfg.blocks[b].successors[1];
  3453. } else {
  3454. smart_branch_opcode = 0;
  3455. target_label = target_label2 = (uint32_t)-1;
  3456. }
  3457. if (!zend_jit_isset_isempty_dim(&dasm_state, opline,
  3458. OP1_INFO(), OP1_REG_ADDR(), 0,
  3459. OP2_INFO(), IS_UNKNOWN,
  3460. zend_may_throw(opline, ssa_op, op_array, ssa),
  3461. smart_branch_opcode, target_label, target_label2,
  3462. NULL)) {
  3463. goto jit_failure;
  3464. }
  3465. goto done;
  3466. case ZEND_FETCH_OBJ_R:
  3467. case ZEND_FETCH_OBJ_IS:
  3468. case ZEND_FETCH_OBJ_W:
  3469. if (opline->op2_type != IS_CONST
  3470. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
  3471. || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
  3472. break;
  3473. }
  3474. ce = NULL;
  3475. ce_is_instanceof = 0;
  3476. on_this = 0;
  3477. if (opline->op1_type == IS_UNUSED) {
  3478. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  3479. op1_addr = 0;
  3480. ce = op_array->scope;
  3481. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  3482. on_this = 1;
  3483. } else {
  3484. op1_info = OP1_INFO();
  3485. if (!(op1_info & MAY_BE_OBJECT)) {
  3486. break;
  3487. }
  3488. op1_addr = OP1_REG_ADDR();
  3489. if (ssa->var_info && ssa->ops) {
  3490. zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
  3491. if (ssa_op->op1_use >= 0) {
  3492. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  3493. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  3494. ce = op1_ssa->ce;
  3495. ce_is_instanceof = op1_ssa->is_instanceof;
  3496. }
  3497. }
  3498. }
  3499. }
  3500. if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op,
  3501. op1_info, op1_addr, 0, ce, ce_is_instanceof, on_this, 0, 0, NULL,
  3502. IS_UNKNOWN,
  3503. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3504. goto jit_failure;
  3505. }
  3506. goto done;
  3507. case ZEND_BIND_GLOBAL:
  3508. if (!ssa->ops || !ssa->var_info) {
  3509. op1_info = MAY_BE_ANY|MAY_BE_REF;
  3510. } else {
  3511. op1_info = OP1_INFO();
  3512. }
  3513. if (!zend_jit_bind_global(&dasm_state, opline, op1_info)) {
  3514. goto jit_failure;
  3515. }
  3516. goto done;
  3517. case ZEND_RECV:
  3518. if (!zend_jit_recv(&dasm_state, opline, op_array)) {
  3519. goto jit_failure;
  3520. }
  3521. goto done;
  3522. case ZEND_RECV_INIT:
  3523. if (!zend_jit_recv_init(&dasm_state, opline, op_array,
  3524. (opline + 1)->opcode != ZEND_RECV_INIT,
  3525. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3526. goto jit_failure;
  3527. }
  3528. goto done;
  3529. case ZEND_FREE:
  3530. case ZEND_FE_FREE:
  3531. if (!zend_jit_free(&dasm_state, opline, OP1_INFO(),
  3532. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3533. goto jit_failure;
  3534. }
  3535. goto done;
  3536. case ZEND_ECHO:
  3537. op1_info = OP1_INFO();
  3538. if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
  3539. break;
  3540. }
  3541. if (!zend_jit_echo(&dasm_state, opline, op1_info)) {
  3542. goto jit_failure;
  3543. }
  3544. goto done;
  3545. case ZEND_STRLEN:
  3546. op1_info = OP1_INFO();
  3547. if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
  3548. break;
  3549. }
  3550. if (!zend_jit_strlen(&dasm_state, opline, op1_info, OP1_REG_ADDR(), RES_REG_ADDR())) {
  3551. goto jit_failure;
  3552. }
  3553. goto done;
  3554. case ZEND_COUNT:
  3555. op1_info = OP1_INFO();
  3556. if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_ARRAY) {
  3557. break;
  3558. }
  3559. if (!zend_jit_count(&dasm_state, opline, op1_info, OP1_REG_ADDR(), RES_REG_ADDR(), zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3560. goto jit_failure;
  3561. }
  3562. goto done;
  3563. case ZEND_FETCH_THIS:
  3564. if (!zend_jit_fetch_this(&dasm_state, opline, op_array, 0)) {
  3565. goto jit_failure;
  3566. }
  3567. goto done;
  3568. case ZEND_SWITCH_LONG:
  3569. case ZEND_SWITCH_STRING:
  3570. case ZEND_MATCH:
  3571. if (!zend_jit_switch(&dasm_state, opline, op_array, ssa, NULL, NULL)) {
  3572. goto jit_failure;
  3573. }
  3574. goto done;
  3575. case ZEND_VERIFY_RETURN_TYPE:
  3576. if (opline->op1_type == IS_UNUSED) {
  3577. /* Always throws */
  3578. break;
  3579. }
  3580. if (opline->op1_type == IS_CONST) {
  3581. /* TODO Different instruction format, has return value */
  3582. break;
  3583. }
  3584. if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
  3585. /* Not worth bothering with */
  3586. break;
  3587. }
  3588. if (OP1_INFO() & MAY_BE_REF) {
  3589. /* TODO May need reference unwrapping. */
  3590. break;
  3591. }
  3592. if (!zend_jit_verify_return_type(&dasm_state, opline, op_array, OP1_INFO())) {
  3593. goto jit_failure;
  3594. }
  3595. goto done;
  3596. case ZEND_FE_RESET_R:
  3597. op1_info = OP1_INFO();
  3598. if ((op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) != MAY_BE_ARRAY) {
  3599. break;
  3600. }
  3601. if (!zend_jit_fe_reset(&dasm_state, opline, op1_info)) {
  3602. goto jit_failure;
  3603. }
  3604. goto done;
  3605. case ZEND_FE_FETCH_R:
  3606. op1_info = OP1_INFO();
  3607. if ((op1_info & MAY_BE_ANY) != MAY_BE_ARRAY) {
  3608. break;
  3609. }
  3610. if (!zend_jit_fe_fetch(&dasm_state, opline, op1_info, OP2_INFO(),
  3611. ssa->cfg.blocks[b].successors[0], opline->opcode, NULL)) {
  3612. goto jit_failure;
  3613. }
  3614. goto done;
  3615. case ZEND_FETCH_CONSTANT:
  3616. if (!zend_jit_fetch_constant(&dasm_state, opline, op_array, ssa, ssa_op, RES_REG_ADDR())) {
  3617. goto jit_failure;
  3618. }
  3619. goto done;
  3620. case ZEND_INIT_METHOD_CALL:
  3621. if (opline->op2_type != IS_CONST
  3622. || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING) {
  3623. break;
  3624. }
  3625. ce = NULL;
  3626. ce_is_instanceof = 0;
  3627. on_this = 0;
  3628. if (opline->op1_type == IS_UNUSED) {
  3629. op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
  3630. op1_addr = 0;
  3631. ce = op_array->scope;
  3632. ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
  3633. on_this = 1;
  3634. } else {
  3635. op1_info = OP1_INFO();
  3636. if (!(op1_info & MAY_BE_OBJECT)) {
  3637. break;
  3638. }
  3639. op1_addr = OP1_REG_ADDR();
  3640. if (ssa->var_info && ssa->ops) {
  3641. zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
  3642. if (ssa_op->op1_use >= 0) {
  3643. zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
  3644. if (op1_ssa->ce && !op1_ssa->ce->create_object) {
  3645. ce = op1_ssa->ce;
  3646. ce_is_instanceof = op1_ssa->is_instanceof;
  3647. }
  3648. }
  3649. }
  3650. }
  3651. if (!zend_jit_init_method_call(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level,
  3652. op1_info, op1_addr, ce, ce_is_instanceof, on_this, 0, NULL,
  3653. NULL, 0, 0)) {
  3654. goto jit_failure;
  3655. }
  3656. goto done;
  3657. case ZEND_ROPE_INIT:
  3658. case ZEND_ROPE_ADD:
  3659. case ZEND_ROPE_END:
  3660. op2_info = OP2_INFO();
  3661. if ((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
  3662. break;
  3663. }
  3664. if (!zend_jit_rope(&dasm_state, opline, op2_info)) {
  3665. goto jit_failure;
  3666. }
  3667. goto done;
  3668. default:
  3669. break;
  3670. }
  3671. }
  3672. switch (opline->opcode) {
  3673. case ZEND_RECV_INIT:
  3674. case ZEND_BIND_GLOBAL:
  3675. if (opline == op_array->opcodes ||
  3676. opline->opcode != op_array->opcodes[i-1].opcode) {
  3677. /* repeatable opcodes */
  3678. if (!zend_jit_handler(&dasm_state, opline,
  3679. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3680. goto jit_failure;
  3681. }
  3682. }
  3683. zend_jit_set_last_valid_opline(opline+1);
  3684. break;
  3685. case ZEND_NOP:
  3686. case ZEND_OP_DATA:
  3687. case ZEND_SWITCH_LONG:
  3688. case ZEND_SWITCH_STRING:
  3689. case ZEND_MATCH:
  3690. break;
  3691. case ZEND_JMP:
  3692. if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) {
  3693. const zend_op *target = OP_JMP_ADDR(opline, opline->op1);
  3694. if (!zend_jit_set_ip(&dasm_state, target)) {
  3695. goto jit_failure;
  3696. }
  3697. }
  3698. if (!zend_jit_jmp(&dasm_state, ssa->cfg.blocks[b].successors[0])) {
  3699. goto jit_failure;
  3700. }
  3701. is_terminated = 1;
  3702. break;
  3703. case ZEND_CATCH:
  3704. case ZEND_FAST_CALL:
  3705. case ZEND_FAST_RET:
  3706. case ZEND_GENERATOR_CREATE:
  3707. case ZEND_GENERATOR_RETURN:
  3708. case ZEND_RETURN_BY_REF:
  3709. case ZEND_RETURN:
  3710. case ZEND_EXIT:
  3711. case ZEND_MATCH_ERROR:
  3712. /* switch through trampoline */
  3713. case ZEND_YIELD:
  3714. case ZEND_YIELD_FROM:
  3715. if (!zend_jit_tail_handler(&dasm_state, opline)) {
  3716. goto jit_failure;
  3717. }
  3718. is_terminated = 1;
  3719. break;
  3720. /* stackless execution */
  3721. case ZEND_INCLUDE_OR_EVAL:
  3722. case ZEND_DO_FCALL:
  3723. case ZEND_DO_UCALL:
  3724. case ZEND_DO_FCALL_BY_NAME:
  3725. if (!zend_jit_call(&dasm_state, opline, b + 1)) {
  3726. goto jit_failure;
  3727. }
  3728. is_terminated = 1;
  3729. break;
  3730. case ZEND_JMPZNZ:
  3731. if (!zend_jit_handler(&dasm_state, opline,
  3732. zend_may_throw(opline, ssa_op, op_array, ssa)) ||
  3733. !zend_jit_cond_jmp(&dasm_state, OP_JMP_ADDR(opline, opline->op2), ssa->cfg.blocks[b].successors[1]) ||
  3734. !zend_jit_jmp(&dasm_state, ssa->cfg.blocks[b].successors[0])) {
  3735. goto jit_failure;
  3736. }
  3737. is_terminated = 1;
  3738. break;
  3739. case ZEND_JMPZ:
  3740. case ZEND_JMPNZ:
  3741. if (opline > op_array->opcodes + ssa->cfg.blocks[b].start &&
  3742. ((opline-1)->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  3743. /* smart branch */
  3744. if (!zend_jit_cond_jmp(&dasm_state, opline + 1, ssa->cfg.blocks[b].successors[0])) {
  3745. goto jit_failure;
  3746. }
  3747. goto done;
  3748. }
  3749. ZEND_FALLTHROUGH;
  3750. case ZEND_JMPZ_EX:
  3751. case ZEND_JMPNZ_EX:
  3752. case ZEND_JMP_SET:
  3753. case ZEND_COALESCE:
  3754. case ZEND_JMP_NULL:
  3755. case ZEND_FE_RESET_R:
  3756. case ZEND_FE_RESET_RW:
  3757. case ZEND_ASSERT_CHECK:
  3758. case ZEND_FE_FETCH_R:
  3759. case ZEND_FE_FETCH_RW:
  3760. if (!zend_jit_handler(&dasm_state, opline,
  3761. zend_may_throw(opline, ssa_op, op_array, ssa)) ||
  3762. !zend_jit_cond_jmp(&dasm_state, opline + 1, ssa->cfg.blocks[b].successors[0])) {
  3763. goto jit_failure;
  3764. }
  3765. break;
  3766. case ZEND_NEW:
  3767. if (!zend_jit_handler(&dasm_state, opline, 1)) {
  3768. return 0;
  3769. }
  3770. if (opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL) {
  3771. zend_class_entry *ce = NULL;
  3772. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNC) {
  3773. if (ssa->ops && ssa->var_info) {
  3774. zend_ssa_var_info *res_ssa = &ssa->var_info[ssa->ops[opline - op_array->opcodes].result_def];
  3775. if (res_ssa->ce && !res_ssa->is_instanceof) {
  3776. ce = res_ssa->ce;
  3777. }
  3778. }
  3779. } else {
  3780. if (opline->op1_type == IS_CONST) {
  3781. zval *zv = RT_CONSTANT(opline, opline->op1);
  3782. if (Z_TYPE_P(zv) == IS_STRING) {
  3783. zval *lc = zv + 1;
  3784. ce = (zend_class_entry*)zend_hash_find_ptr(EG(class_table), Z_STR_P(lc));
  3785. }
  3786. }
  3787. }
  3788. i++;
  3789. if (!ce || !(ce->ce_flags & ZEND_ACC_LINKED) || ce->constructor) {
  3790. const zend_op *next_opline = opline + 1;
  3791. zend_jit_cond_jmp(&dasm_state, next_opline, ssa->cfg.blocks[b].successors[0]);
  3792. if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) {
  3793. zend_jit_call(&dasm_state, next_opline, b + 1);
  3794. is_terminated = 1;
  3795. } else {
  3796. zend_jit_do_fcall(&dasm_state, next_opline, op_array, ssa, call_level, b + 1, NULL);
  3797. }
  3798. }
  3799. /* We skip over the DO_FCALL, so decrement call_level ourselves. */
  3800. call_level--;
  3801. }
  3802. break;
  3803. default:
  3804. if (!zend_jit_handler(&dasm_state, opline,
  3805. zend_may_throw(opline, ssa_op, op_array, ssa))) {
  3806. goto jit_failure;
  3807. }
  3808. if (i == end
  3809. && (opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
  3810. /* smart branch split across basic blocks */
  3811. if (!zend_jit_cond_jmp(&dasm_state, opline + 2, ssa->cfg.blocks[b+1].successors[0])) {
  3812. goto jit_failure;
  3813. }
  3814. if (!zend_jit_jmp(&dasm_state, ssa->cfg.blocks[b+1].successors[1])) {
  3815. goto jit_failure;
  3816. }
  3817. is_terminated = 1;
  3818. }
  3819. }
  3820. done:
  3821. switch (opline->opcode) {
  3822. case ZEND_DO_FCALL:
  3823. case ZEND_DO_ICALL:
  3824. case ZEND_DO_UCALL:
  3825. case ZEND_DO_FCALL_BY_NAME:
  3826. case ZEND_CALLABLE_CONVERT:
  3827. call_level--;
  3828. }
  3829. }
  3830. }
  3831. handler = dasm_link_and_encode(&dasm_state, op_array, ssa, rt_opline, ra, NULL, 0,
  3832. (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) ? SP_ADJ_VM : SP_ADJ_RET, SP_ADJ_JIT);
  3833. if (!handler) {
  3834. goto jit_failure;
  3835. }
  3836. dasm_free(&dasm_state);
  3837. if (JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL)) {
  3838. zend_arena_release(&CG(arena), checkpoint);
  3839. }
  3840. return SUCCESS;
  3841. jit_failure:
  3842. if (dasm_state) {
  3843. dasm_free(&dasm_state);
  3844. }
  3845. if (JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL)) {
  3846. zend_arena_release(&CG(arena), checkpoint);
  3847. }
  3848. return FAILURE;
  3849. }
  3850. static int zend_jit_collect_calls(zend_op_array *op_array, zend_script *script)
  3851. {
  3852. zend_func_info *func_info;
  3853. if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC ||
  3854. JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST ||
  3855. JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
  3856. func_info = ZEND_FUNC_INFO(op_array);
  3857. } else {
  3858. func_info = zend_arena_calloc(&CG(arena), 1, sizeof(zend_func_info));
  3859. ZEND_SET_FUNC_INFO(op_array, func_info);
  3860. }
  3861. return zend_analyze_calls(&CG(arena), script, ZEND_CALL_TREE, op_array, func_info);
  3862. }
  3863. static void zend_jit_cleanup_func_info(zend_op_array *op_array)
  3864. {
  3865. zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
  3866. zend_call_info *caller_info, *callee_info;
  3867. if (func_info) {
  3868. caller_info = func_info->caller_info;
  3869. callee_info = func_info->callee_info;
  3870. if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC ||
  3871. JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST ||
  3872. JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
  3873. func_info->num = 0;
  3874. func_info->flags &= ZEND_FUNC_JIT_ON_FIRST_EXEC
  3875. | ZEND_FUNC_JIT_ON_PROF_REQUEST
  3876. | ZEND_FUNC_JIT_ON_HOT_COUNTERS
  3877. | ZEND_FUNC_JIT_ON_HOT_TRACE;
  3878. memset(&func_info->ssa, 0, sizeof(zend_func_info) - offsetof(zend_func_info, ssa));
  3879. } else {
  3880. ZEND_SET_FUNC_INFO(op_array, NULL);
  3881. }
  3882. while (caller_info) {
  3883. if (caller_info->caller_op_array) {
  3884. zend_jit_cleanup_func_info(caller_info->caller_op_array);
  3885. }
  3886. caller_info = caller_info->next_caller;
  3887. }
  3888. while (callee_info) {
  3889. if (callee_info->callee_func && callee_info->callee_func->type == ZEND_USER_FUNCTION) {
  3890. zend_jit_cleanup_func_info(&callee_info->callee_func->op_array);
  3891. }
  3892. callee_info = callee_info->next_callee;
  3893. }
  3894. }
  3895. }
  3896. static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, const zend_op *rt_opline)
  3897. {
  3898. zend_ssa ssa;
  3899. void *checkpoint;
  3900. zend_func_info *func_info;
  3901. if (*dasm_ptr == dasm_end) {
  3902. return FAILURE;
  3903. }
  3904. checkpoint = zend_arena_checkpoint(CG(arena));
  3905. /* Build SSA */
  3906. memset(&ssa, 0, sizeof(zend_ssa));
  3907. if (zend_jit_op_array_analyze1(op_array, script, &ssa) != SUCCESS) {
  3908. goto jit_failure;
  3909. }
  3910. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNCS) {
  3911. if (zend_jit_collect_calls(op_array, script) != SUCCESS) {
  3912. goto jit_failure;
  3913. }
  3914. func_info = ZEND_FUNC_INFO(op_array);
  3915. func_info->call_map = zend_build_call_map(&CG(arena), func_info, op_array);
  3916. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  3917. zend_init_func_return_info(op_array, script, &func_info->return_info);
  3918. }
  3919. }
  3920. if (zend_jit_op_array_analyze2(op_array, script, &ssa, ZCG(accel_directives).optimization_level) != SUCCESS) {
  3921. goto jit_failure;
  3922. }
  3923. if (JIT_G(debug) & ZEND_JIT_DEBUG_SSA) {
  3924. zend_dump_op_array(op_array, ZEND_DUMP_HIDE_UNREACHABLE|ZEND_DUMP_RC_INFERENCE|ZEND_DUMP_SSA, "JIT", &ssa);
  3925. }
  3926. if (zend_jit(op_array, &ssa, rt_opline) != SUCCESS) {
  3927. goto jit_failure;
  3928. }
  3929. zend_jit_cleanup_func_info(op_array);
  3930. zend_arena_release(&CG(arena), checkpoint);
  3931. return SUCCESS;
  3932. jit_failure:
  3933. zend_jit_cleanup_func_info(op_array);
  3934. zend_arena_release(&CG(arena), checkpoint);
  3935. return FAILURE;
  3936. }
  3937. /* Run-time JIT handler */
  3938. static int ZEND_FASTCALL zend_runtime_jit(void)
  3939. {
  3940. zend_execute_data *execute_data = EG(current_execute_data);
  3941. zend_op_array *op_array = &EX(func)->op_array;
  3942. zend_op *opline = op_array->opcodes;
  3943. zend_jit_op_array_extension *jit_extension;
  3944. bool do_bailout = 0;
  3945. zend_shared_alloc_lock();
  3946. if (ZEND_FUNC_INFO(op_array)) {
  3947. SHM_UNPROTECT();
  3948. zend_jit_unprotect();
  3949. zend_try {
  3950. /* restore original opcode handlers */
  3951. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  3952. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  3953. opline++;
  3954. }
  3955. }
  3956. jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
  3957. opline->handler = jit_extension->orig_handler;
  3958. /* perform real JIT for this function */
  3959. zend_real_jit_func(op_array, NULL, NULL);
  3960. } zend_catch {
  3961. do_bailout = 0;
  3962. } zend_end_try();
  3963. zend_jit_protect();
  3964. SHM_PROTECT();
  3965. }
  3966. zend_shared_alloc_unlock();
  3967. if (do_bailout) {
  3968. zend_bailout();
  3969. }
  3970. /* JIT-ed code is going to be called by VM */
  3971. return 0;
  3972. }
  3973. void zend_jit_check_funcs(HashTable *function_table, bool is_method) {
  3974. zend_op *opline;
  3975. zend_function *func;
  3976. zend_op_array *op_array;
  3977. uintptr_t counter;
  3978. zend_jit_op_array_extension *jit_extension;
  3979. ZEND_HASH_REVERSE_FOREACH_PTR(function_table, func) {
  3980. if (func->type == ZEND_INTERNAL_FUNCTION) {
  3981. break;
  3982. }
  3983. op_array = &func->op_array;
  3984. opline = op_array->opcodes;
  3985. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  3986. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  3987. opline++;
  3988. }
  3989. }
  3990. if (opline->handler == zend_jit_profile_jit_handler) {
  3991. if (!RUN_TIME_CACHE(op_array)) {
  3992. continue;
  3993. }
  3994. counter = (uintptr_t)ZEND_COUNTER_INFO(op_array);
  3995. ZEND_COUNTER_INFO(op_array) = 0;
  3996. jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
  3997. opline->handler = jit_extension->orig_handler;
  3998. if (((double)counter / (double)zend_jit_profile_counter) > JIT_G(prof_threshold)) {
  3999. zend_real_jit_func(op_array, NULL, NULL);
  4000. }
  4001. }
  4002. } ZEND_HASH_FOREACH_END();
  4003. }
  4004. void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend_op *opline)
  4005. {
  4006. zend_op_array *op_array = &EX(func)->op_array;
  4007. zend_jit_op_array_hot_extension *jit_extension;
  4008. uint32_t i;
  4009. bool do_bailout = 0;
  4010. zend_shared_alloc_lock();
  4011. jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(op_array);
  4012. if (jit_extension) {
  4013. SHM_UNPROTECT();
  4014. zend_jit_unprotect();
  4015. zend_try {
  4016. for (i = 0; i < op_array->last; i++) {
  4017. op_array->opcodes[i].handler = jit_extension->orig_handlers[i];
  4018. }
  4019. /* perform real JIT for this function */
  4020. zend_real_jit_func(op_array, NULL, opline);
  4021. } zend_catch {
  4022. do_bailout = 1;
  4023. } zend_end_try();
  4024. zend_jit_protect();
  4025. SHM_PROTECT();
  4026. }
  4027. zend_shared_alloc_unlock();
  4028. if (do_bailout) {
  4029. zend_bailout();
  4030. }
  4031. /* JIT-ed code is going to be called by VM */
  4032. }
  4033. static void zend_jit_setup_hot_counters_ex(zend_op_array *op_array, zend_cfg *cfg)
  4034. {
  4035. if (JIT_G(hot_func)) {
  4036. zend_op *opline = op_array->opcodes;
  4037. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  4038. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  4039. opline++;
  4040. }
  4041. }
  4042. opline->handler = (const void*)zend_jit_func_hot_counter_handler;
  4043. }
  4044. if (JIT_G(hot_loop)) {
  4045. uint32_t i;
  4046. for (i = 0; i < cfg->blocks_count; i++) {
  4047. if ((cfg->blocks[i].flags & ZEND_BB_REACHABLE) &&
  4048. (cfg->blocks[i].flags & ZEND_BB_LOOP_HEADER)) {
  4049. op_array->opcodes[cfg->blocks[i].start].handler =
  4050. (const void*)zend_jit_loop_hot_counter_handler;
  4051. }
  4052. }
  4053. }
  4054. }
  4055. static int zend_jit_restart_hot_counters(zend_op_array *op_array)
  4056. {
  4057. zend_jit_op_array_hot_extension *jit_extension;
  4058. zend_cfg cfg;
  4059. uint32_t i;
  4060. jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(op_array);
  4061. for (i = 0; i < op_array->last; i++) {
  4062. op_array->opcodes[i].handler = jit_extension->orig_handlers[i];
  4063. }
  4064. if (zend_jit_build_cfg(op_array, &cfg) != SUCCESS) {
  4065. return FAILURE;
  4066. }
  4067. zend_jit_setup_hot_counters_ex(op_array, &cfg);
  4068. return SUCCESS;
  4069. }
  4070. static int zend_jit_setup_hot_counters(zend_op_array *op_array)
  4071. {
  4072. zend_jit_op_array_hot_extension *jit_extension;
  4073. zend_cfg cfg;
  4074. uint32_t i;
  4075. ZEND_ASSERT(zend_jit_func_hot_counter_handler != NULL);
  4076. ZEND_ASSERT(zend_jit_loop_hot_counter_handler != NULL);
  4077. if (zend_jit_build_cfg(op_array, &cfg) != SUCCESS) {
  4078. return FAILURE;
  4079. }
  4080. jit_extension = (zend_jit_op_array_hot_extension*)zend_shared_alloc(sizeof(zend_jit_op_array_hot_extension) + (op_array->last - 1) * sizeof(void*));
  4081. if (!jit_extension) {
  4082. return FAILURE;
  4083. }
  4084. memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
  4085. jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_HOT_COUNTERS;
  4086. jit_extension->counter = &zend_jit_hot_counters[zend_jit_op_array_hash(op_array) & (ZEND_HOT_COUNTERS_COUNT - 1)];
  4087. for (i = 0; i < op_array->last; i++) {
  4088. jit_extension->orig_handlers[i] = op_array->opcodes[i].handler;
  4089. }
  4090. ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
  4091. zend_jit_setup_hot_counters_ex(op_array, &cfg);
  4092. zend_shared_alloc_register_xlat_entry(op_array->opcodes, jit_extension);
  4093. return SUCCESS;
  4094. }
  4095. #include "jit/zend_jit_trace.c"
  4096. ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
  4097. {
  4098. if (dasm_ptr == NULL) {
  4099. return FAILURE;
  4100. }
  4101. if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC) {
  4102. zend_jit_op_array_extension *jit_extension;
  4103. zend_op *opline = op_array->opcodes;
  4104. if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
  4105. ZEND_SET_FUNC_INFO(op_array, NULL);
  4106. zend_error(E_WARNING, "Preloading is incompatible with first-exec and profile triggered JIT");
  4107. return SUCCESS;
  4108. }
  4109. /* Set run-time JIT handler */
  4110. ZEND_ASSERT(zend_jit_runtime_jit_handler != NULL);
  4111. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  4112. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  4113. opline++;
  4114. }
  4115. }
  4116. jit_extension = (zend_jit_op_array_extension*)zend_shared_alloc(sizeof(zend_jit_op_array_extension));
  4117. if (!jit_extension) {
  4118. return FAILURE;
  4119. }
  4120. memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
  4121. jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_FIRST_EXEC;
  4122. jit_extension->orig_handler = (void*)opline->handler;
  4123. ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
  4124. opline->handler = (const void*)zend_jit_runtime_jit_handler;
  4125. zend_shared_alloc_register_xlat_entry(op_array->opcodes, jit_extension);
  4126. return SUCCESS;
  4127. } else if (JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST) {
  4128. zend_jit_op_array_extension *jit_extension;
  4129. zend_op *opline = op_array->opcodes;
  4130. if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
  4131. ZEND_SET_FUNC_INFO(op_array, NULL);
  4132. zend_error(E_WARNING, "Preloading is incompatible with first-exec and profile triggered JIT");
  4133. return SUCCESS;
  4134. }
  4135. ZEND_ASSERT(zend_jit_profile_jit_handler != NULL);
  4136. if (op_array->function_name) {
  4137. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  4138. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  4139. opline++;
  4140. }
  4141. }
  4142. jit_extension = (zend_jit_op_array_extension*)zend_shared_alloc(sizeof(zend_jit_op_array_extension));
  4143. if (!jit_extension) {
  4144. return FAILURE;
  4145. }
  4146. memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
  4147. jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_PROF_REQUEST;
  4148. jit_extension->orig_handler = (void*)opline->handler;
  4149. ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
  4150. opline->handler = (const void*)zend_jit_profile_jit_handler;
  4151. zend_shared_alloc_register_xlat_entry(op_array->opcodes, jit_extension);
  4152. }
  4153. return SUCCESS;
  4154. } else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
  4155. return zend_jit_setup_hot_counters(op_array);
  4156. } else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
  4157. return zend_jit_setup_hot_trace_counters(op_array);
  4158. } else if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) {
  4159. return zend_real_jit_func(op_array, script, NULL);
  4160. } else {
  4161. ZEND_UNREACHABLE();
  4162. }
  4163. }
  4164. ZEND_EXT_API int zend_jit_script(zend_script *script)
  4165. {
  4166. void *checkpoint;
  4167. zend_call_graph call_graph;
  4168. zend_func_info *info;
  4169. int i;
  4170. if (dasm_ptr == NULL || *dasm_ptr == dasm_end) {
  4171. return FAILURE;
  4172. }
  4173. checkpoint = zend_arena_checkpoint(CG(arena));
  4174. call_graph.op_arrays_count = 0;
  4175. if (zend_build_call_graph(&CG(arena), script, &call_graph) != SUCCESS) {
  4176. goto jit_failure;
  4177. }
  4178. zend_analyze_call_graph(&CG(arena), script, &call_graph);
  4179. if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC ||
  4180. JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST ||
  4181. JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS ||
  4182. JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
  4183. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4184. if (zend_jit_op_array(call_graph.op_arrays[i], script) != SUCCESS) {
  4185. goto jit_failure;
  4186. }
  4187. }
  4188. } else if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) {
  4189. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4190. info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
  4191. if (info) {
  4192. if (zend_jit_op_array_analyze1(call_graph.op_arrays[i], script, &info->ssa) != SUCCESS) {
  4193. goto jit_failure;
  4194. }
  4195. info->flags = info->ssa.cfg.flags;
  4196. }
  4197. }
  4198. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4199. info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
  4200. if (info) {
  4201. info->call_map = zend_build_call_map(&CG(arena), info, call_graph.op_arrays[i]);
  4202. if (call_graph.op_arrays[i]->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  4203. zend_init_func_return_info(call_graph.op_arrays[i], script, &info->return_info);
  4204. }
  4205. }
  4206. }
  4207. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4208. info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
  4209. if (info) {
  4210. if (zend_jit_op_array_analyze2(call_graph.op_arrays[i], script, &info->ssa, ZCG(accel_directives).optimization_level) != SUCCESS) {
  4211. goto jit_failure;
  4212. }
  4213. info->flags = info->ssa.cfg.flags;
  4214. }
  4215. }
  4216. if (JIT_G(debug) & ZEND_JIT_DEBUG_SSA) {
  4217. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4218. info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
  4219. if (info) {
  4220. zend_dump_op_array(call_graph.op_arrays[i], ZEND_DUMP_HIDE_UNREACHABLE|ZEND_DUMP_RC_INFERENCE|ZEND_DUMP_SSA, "JIT", &info->ssa);
  4221. }
  4222. }
  4223. }
  4224. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4225. info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
  4226. if (info) {
  4227. if (zend_jit(call_graph.op_arrays[i], &info->ssa, NULL) != SUCCESS) {
  4228. goto jit_failure;
  4229. }
  4230. }
  4231. }
  4232. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4233. ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
  4234. }
  4235. } else {
  4236. ZEND_UNREACHABLE();
  4237. }
  4238. zend_arena_release(&CG(arena), checkpoint);
  4239. if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
  4240. || JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
  4241. || JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
  4242. || JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
  4243. zend_class_entry *ce;
  4244. zend_op_array *op_array;
  4245. ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
  4246. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  4247. if (!ZEND_FUNC_INFO(op_array)) {
  4248. void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
  4249. if (jit_extension) {
  4250. ZEND_SET_FUNC_INFO(op_array, jit_extension);
  4251. }
  4252. }
  4253. } ZEND_HASH_FOREACH_END();
  4254. } ZEND_HASH_FOREACH_END();
  4255. }
  4256. return SUCCESS;
  4257. jit_failure:
  4258. if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) {
  4259. for (i = 0; i < call_graph.op_arrays_count; i++) {
  4260. ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
  4261. }
  4262. }
  4263. zend_arena_release(&CG(arena), checkpoint);
  4264. return FAILURE;
  4265. }
  4266. ZEND_EXT_API void zend_jit_unprotect(void)
  4267. {
  4268. #ifdef HAVE_MPROTECT
  4269. if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) {
  4270. int opts = PROT_READ | PROT_WRITE;
  4271. #ifdef ZTS
  4272. /* TODO: EXEC+WRITE is not supported in macOS. Removing EXEC is still buggy as
  4273. * other threads, which are executing the JITed code, would crash anyway. */
  4274. # ifndef __APPLE__
  4275. /* Another thread may be executing JITed code. */
  4276. opts |= PROT_EXEC;
  4277. # endif
  4278. #endif
  4279. if (mprotect(dasm_buf, dasm_size, opts) != 0) {
  4280. fprintf(stderr, "mprotect() failed [%d] %s\n", errno, strerror(errno));
  4281. }
  4282. }
  4283. #elif _WIN32
  4284. if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) {
  4285. DWORD old, new;
  4286. #ifdef ZTS
  4287. new = PAGE_EXECUTE_READWRITE;
  4288. #else
  4289. new = PAGE_READWRITE;
  4290. #endif
  4291. if (!VirtualProtect(dasm_buf, dasm_size, new, &old)) {
  4292. DWORD err = GetLastError();
  4293. char *msg = php_win32_error_to_msg(err);
  4294. fprintf(stderr, "VirtualProtect() failed [%u] %s\n", err, msg);
  4295. php_win32_error_msg_free(msg);
  4296. }
  4297. }
  4298. #endif
  4299. }
  4300. ZEND_EXT_API void zend_jit_protect(void)
  4301. {
  4302. #ifdef HAVE_MPROTECT
  4303. if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) {
  4304. if (mprotect(dasm_buf, dasm_size, PROT_READ | PROT_EXEC) != 0) {
  4305. fprintf(stderr, "mprotect() failed [%d] %s\n", errno, strerror(errno));
  4306. }
  4307. }
  4308. #elif _WIN32
  4309. if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) {
  4310. DWORD old;
  4311. if (!VirtualProtect(dasm_buf, dasm_size, PAGE_EXECUTE_READ, &old)) {
  4312. DWORD err = GetLastError();
  4313. char *msg = php_win32_error_to_msg(err);
  4314. fprintf(stderr, "VirtualProtect() failed [%u] %s\n", err, msg);
  4315. php_win32_error_msg_free(msg);
  4316. }
  4317. }
  4318. #endif
  4319. }
  4320. static void zend_jit_init_handlers(void)
  4321. {
  4322. if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
  4323. zend_jit_runtime_jit_handler = dasm_labels[zend_lbhybrid_runtime_jit];
  4324. zend_jit_profile_jit_handler = dasm_labels[zend_lbhybrid_profile_jit];
  4325. zend_jit_func_hot_counter_handler = dasm_labels[zend_lbhybrid_func_hot_counter];
  4326. zend_jit_loop_hot_counter_handler = dasm_labels[zend_lbhybrid_loop_hot_counter];
  4327. zend_jit_func_trace_counter_handler = dasm_labels[zend_lbhybrid_func_trace_counter];
  4328. zend_jit_ret_trace_counter_handler = dasm_labels[zend_lbhybrid_ret_trace_counter];
  4329. zend_jit_loop_trace_counter_handler = dasm_labels[zend_lbhybrid_loop_trace_counter];
  4330. } else {
  4331. zend_jit_runtime_jit_handler = (const void*)zend_runtime_jit;
  4332. zend_jit_profile_jit_handler = (const void*)zend_jit_profile_helper;
  4333. zend_jit_func_hot_counter_handler = (const void*)zend_jit_func_counter_helper;
  4334. zend_jit_loop_hot_counter_handler = (const void*)zend_jit_loop_counter_helper;
  4335. zend_jit_func_trace_counter_handler = (const void*)zend_jit_func_trace_helper;
  4336. zend_jit_ret_trace_counter_handler = (const void*)zend_jit_ret_trace_helper;
  4337. zend_jit_loop_trace_counter_handler = (const void*)zend_jit_loop_trace_helper;
  4338. }
  4339. }
  4340. static int zend_jit_make_stubs(void)
  4341. {
  4342. dasm_State* dasm_state = NULL;
  4343. uint32_t i;
  4344. dasm_init(&dasm_state, DASM_MAXSECTION);
  4345. dasm_setupglobal(&dasm_state, dasm_labels, zend_lb_MAX);
  4346. for (i = 0; i < sizeof(zend_jit_stubs)/sizeof(zend_jit_stubs[0]); i++) {
  4347. dasm_setup(&dasm_state, dasm_actions);
  4348. if (!zend_jit_stubs[i].stub(&dasm_state)) {
  4349. return 0;
  4350. }
  4351. if (!dasm_link_and_encode(&dasm_state, NULL, NULL, NULL, NULL, zend_jit_stubs[i].name, 0,
  4352. zend_jit_stubs[i].offset, zend_jit_stubs[i].adjustment)) {
  4353. return 0;
  4354. }
  4355. }
  4356. zend_jit_init_handlers();
  4357. dasm_free(&dasm_state);
  4358. return 1;
  4359. }
  4360. static void zend_jit_globals_ctor(zend_jit_globals *jit_globals)
  4361. {
  4362. memset(jit_globals, 0, sizeof(zend_jit_globals));
  4363. zend_jit_trace_init_caches();
  4364. }
  4365. static int zend_jit_parse_config_num(zend_long jit)
  4366. {
  4367. if (jit == 0) {
  4368. JIT_G(on) = 0;
  4369. return SUCCESS;
  4370. }
  4371. if (jit < 0) return FAILURE;
  4372. if (jit % 10 == 0 || jit % 10 > 5) return FAILURE;
  4373. JIT_G(opt_level) = jit % 10;
  4374. jit /= 10;
  4375. if (jit % 10 > 5) return FAILURE;
  4376. JIT_G(trigger) = jit % 10;
  4377. jit /= 10;
  4378. if (jit % 10 > 2) return FAILURE;
  4379. JIT_G(opt_flags) = jit % 10;
  4380. jit /= 10;
  4381. if (jit % 10 > 1) return FAILURE;
  4382. JIT_G(opt_flags) |= ((jit % 10) ? ZEND_JIT_CPU_AVX : 0);
  4383. if (jit / 10 != 0) return FAILURE;
  4384. JIT_G(on) = 1;
  4385. return SUCCESS;
  4386. }
  4387. ZEND_EXT_API int zend_jit_config(zend_string *jit, int stage)
  4388. {
  4389. if (stage != ZEND_INI_STAGE_STARTUP && !JIT_G(enabled)) {
  4390. if (stage == ZEND_INI_STAGE_RUNTIME) {
  4391. zend_error(E_WARNING, "Cannot change opcache.jit setting at run-time (JIT is disabled)");
  4392. }
  4393. return FAILURE;
  4394. }
  4395. if (ZSTR_LEN(jit) == 0
  4396. || zend_string_equals_literal_ci(jit, "disable")) {
  4397. JIT_G(enabled) = 0;
  4398. JIT_G(on) = 0;
  4399. return SUCCESS;
  4400. } else if (zend_string_equals_literal_ci(jit, "0")
  4401. || zend_string_equals_literal_ci(jit, "off")
  4402. || zend_string_equals_literal_ci(jit, "no")
  4403. || zend_string_equals_literal_ci(jit, "false")) {
  4404. JIT_G(enabled) = 1;
  4405. JIT_G(on) = 0;
  4406. return SUCCESS;
  4407. } else if (zend_string_equals_literal_ci(jit, "1")
  4408. || zend_string_equals_literal_ci(jit, "on")
  4409. || zend_string_equals_literal_ci(jit, "yes")
  4410. || zend_string_equals_literal_ci(jit, "true")
  4411. || zend_string_equals_literal_ci(jit, "tracing")) {
  4412. JIT_G(enabled) = 1;
  4413. JIT_G(on) = 1;
  4414. JIT_G(opt_level) = ZEND_JIT_LEVEL_OPT_FUNCS;
  4415. JIT_G(trigger) = ZEND_JIT_ON_HOT_TRACE;
  4416. JIT_G(opt_flags) = ZEND_JIT_REG_ALLOC_GLOBAL | ZEND_JIT_CPU_AVX;
  4417. return SUCCESS;
  4418. } else if (zend_string_equals_literal_ci(jit, "function")) {
  4419. JIT_G(enabled) = 1;
  4420. JIT_G(on) = 1;
  4421. JIT_G(opt_level) = ZEND_JIT_LEVEL_OPT_SCRIPT;
  4422. JIT_G(trigger) = ZEND_JIT_ON_SCRIPT_LOAD;
  4423. JIT_G(opt_flags) = ZEND_JIT_REG_ALLOC_GLOBAL | ZEND_JIT_CPU_AVX;
  4424. return SUCCESS;
  4425. } else {
  4426. char *end;
  4427. zend_long num = ZEND_STRTOL(ZSTR_VAL(jit), &end, 10);
  4428. if (end != ZSTR_VAL(jit) + ZSTR_LEN(jit) || zend_jit_parse_config_num(num) != SUCCESS) {
  4429. goto failure;
  4430. }
  4431. JIT_G(enabled) = 1;
  4432. return SUCCESS;
  4433. }
  4434. failure:
  4435. zend_error(E_WARNING, "Invalid \"opcache.jit\" setting. Should be \"disable\", \"on\", \"off\", \"tracing\", \"function\" or 4-digit number");
  4436. JIT_G(enabled) = 0;
  4437. JIT_G(on) = 0;
  4438. return FAILURE;
  4439. }
  4440. ZEND_EXT_API int zend_jit_debug_config(zend_long old_val, zend_long new_val, int stage)
  4441. {
  4442. if (stage != ZEND_INI_STAGE_STARTUP) {
  4443. if (((old_val ^ new_val) & ZEND_JIT_DEBUG_PERSISTENT) != 0) {
  4444. if (stage == ZEND_INI_STAGE_RUNTIME) {
  4445. zend_error(E_WARNING, "Some opcache.jit_debug bits cannot be changed after startup");
  4446. }
  4447. return FAILURE;
  4448. }
  4449. #ifdef HAVE_DISASM
  4450. if (new_val & (ZEND_JIT_DEBUG_ASM|ZEND_JIT_DEBUG_ASM_STUBS)) {
  4451. if (JIT_G(enabled) && !JIT_G(symbols) && !zend_jit_disasm_init()) {
  4452. // TODO: error reporting and cleanup ???
  4453. return FAILURE;
  4454. }
  4455. // TODO: symbols for JIT-ed code compiled before are missing ???
  4456. }
  4457. #endif
  4458. }
  4459. return SUCCESS;
  4460. }
  4461. ZEND_EXT_API void zend_jit_init(void)
  4462. {
  4463. #ifdef ZTS
  4464. jit_globals_id = ts_allocate_id(&jit_globals_id, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, NULL);
  4465. #else
  4466. zend_jit_globals_ctor(&jit_globals);
  4467. #endif
  4468. }
  4469. ZEND_EXT_API int zend_jit_check_support(void)
  4470. {
  4471. int i;
  4472. zend_jit_vm_kind = zend_vm_kind();
  4473. if (zend_jit_vm_kind != ZEND_VM_KIND_CALL &&
  4474. zend_jit_vm_kind != ZEND_VM_KIND_HYBRID) {
  4475. zend_error(E_WARNING, "JIT is compatible only with CALL and HYBRID VM. JIT disabled.");
  4476. JIT_G(enabled) = 0;
  4477. JIT_G(on) = 0;
  4478. return FAILURE;
  4479. }
  4480. if (zend_execute_ex != execute_ex) {
  4481. if (strcmp(sapi_module.name, "phpdbg") != 0) {
  4482. zend_error(E_WARNING, "JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled.");
  4483. }
  4484. JIT_G(enabled) = 0;
  4485. JIT_G(on) = 0;
  4486. return FAILURE;
  4487. }
  4488. for (i = 0; i <= 256; i++) {
  4489. switch (i) {
  4490. /* JIT has no effect on these opcodes */
  4491. case ZEND_BEGIN_SILENCE:
  4492. case ZEND_END_SILENCE:
  4493. case ZEND_EXIT:
  4494. break;
  4495. default:
  4496. if (zend_get_user_opcode_handler(i) != NULL) {
  4497. zend_error(E_WARNING, "JIT is incompatible with third party extensions that setup user opcode handlers. JIT disabled.");
  4498. JIT_G(enabled) = 0;
  4499. JIT_G(on) = 0;
  4500. return FAILURE;
  4501. }
  4502. }
  4503. }
  4504. return SUCCESS;
  4505. }
  4506. ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, bool reattached)
  4507. {
  4508. int ret;
  4509. zend_jit_halt_op = zend_get_halt_op();
  4510. if (zend_jit_setup() != SUCCESS) {
  4511. // TODO: error reporting and cleanup ???
  4512. return FAILURE;
  4513. }
  4514. zend_jit_profile_counter_rid = zend_get_op_array_extension_handle(ACCELERATOR_PRODUCT_NAME);
  4515. #ifdef HAVE_GDB
  4516. zend_jit_gdb_init();
  4517. #endif
  4518. #ifdef HAVE_OPROFILE
  4519. if (JIT_G(debug) & ZEND_JIT_DEBUG_OPROFILE) {
  4520. if (!zend_jit_oprofile_startup()) {
  4521. // TODO: error reporting and cleanup ???
  4522. return FAILURE;
  4523. }
  4524. }
  4525. #endif
  4526. dasm_buf = buf;
  4527. dasm_size = size;
  4528. #ifdef HAVE_MPROTECT
  4529. if (JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP)) {
  4530. if (mprotect(dasm_buf, dasm_size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
  4531. fprintf(stderr, "mprotect() failed [%d] %s\n", errno, strerror(errno));
  4532. }
  4533. } else {
  4534. if (mprotect(dasm_buf, dasm_size, PROT_READ | PROT_EXEC) != 0) {
  4535. fprintf(stderr, "mprotect() failed [%d] %s\n", errno, strerror(errno));
  4536. }
  4537. }
  4538. #elif _WIN32
  4539. if (JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP)) {
  4540. DWORD old;
  4541. if (!VirtualProtect(dasm_buf, dasm_size, PAGE_EXECUTE_READWRITE, &old)) {
  4542. DWORD err = GetLastError();
  4543. char *msg = php_win32_error_to_msg(err);
  4544. fprintf(stderr, "VirtualProtect() failed [%u] %s\n", err, msg);
  4545. php_win32_error_msg_free(msg);
  4546. }
  4547. } else {
  4548. DWORD old;
  4549. if (!VirtualProtect(dasm_buf, dasm_size, PAGE_EXECUTE_READ, &old)) {
  4550. DWORD err = GetLastError();
  4551. char *msg = php_win32_error_to_msg(err);
  4552. fprintf(stderr, "VirtualProtect() failed [%u] %s\n", err, msg);
  4553. php_win32_error_msg_free(msg);
  4554. }
  4555. }
  4556. #endif
  4557. dasm_ptr = dasm_end = (void*)(((char*)dasm_buf) + size - sizeof(*dasm_ptr) * 2);
  4558. if (!reattached) {
  4559. zend_jit_unprotect();
  4560. *dasm_ptr = dasm_buf;
  4561. #if _WIN32
  4562. /* reserve space for global labels */
  4563. *dasm_ptr = (void**)*dasm_ptr + zend_lb_MAX;
  4564. #endif
  4565. zend_jit_protect();
  4566. }
  4567. #ifdef HAVE_DISASM
  4568. if (JIT_G(debug) & (ZEND_JIT_DEBUG_ASM|ZEND_JIT_DEBUG_ASM_STUBS)) {
  4569. if (!zend_jit_disasm_init()) {
  4570. // TODO: error reporting and cleanup ???
  4571. return FAILURE;
  4572. }
  4573. }
  4574. #endif
  4575. #ifdef HAVE_PERFTOOLS
  4576. if (JIT_G(debug) & ZEND_JIT_DEBUG_PERF_DUMP) {
  4577. zend_jit_perf_jitdump_open();
  4578. }
  4579. #endif
  4580. if (!reattached) {
  4581. zend_jit_unprotect();
  4582. ret = zend_jit_make_stubs();
  4583. #if _WIN32
  4584. /* save global labels */
  4585. memcpy(dasm_buf, dasm_labels, sizeof(void*) * zend_lb_MAX);
  4586. #endif
  4587. zend_jit_protect();
  4588. if (!ret) {
  4589. // TODO: error reporting and cleanup ???
  4590. return FAILURE;
  4591. }
  4592. } else {
  4593. #if _WIN32
  4594. /* restore global labels */
  4595. memcpy(dasm_labels, dasm_buf, sizeof(void*) * zend_lb_MAX);
  4596. zend_jit_init_handlers();
  4597. #endif
  4598. }
  4599. if (zend_jit_trace_startup(reattached) != SUCCESS) {
  4600. return FAILURE;
  4601. }
  4602. zend_jit_unprotect();
  4603. #if ZEND_JIT_TARGET_ARM64
  4604. /* reserve space for global labels veneers */
  4605. dasm_labels_veneers = *dasm_ptr;
  4606. *dasm_ptr = (void**)*dasm_ptr + ZEND_MM_ALIGNED_SIZE_EX(zend_lb_MAX, DASM_ALIGNMENT);
  4607. memset(dasm_labels_veneers, 0, sizeof(void*) * ZEND_MM_ALIGNED_SIZE_EX(zend_lb_MAX, DASM_ALIGNMENT));
  4608. #endif
  4609. /* save JIT buffer pos */
  4610. dasm_ptr[1] = dasm_ptr[0];
  4611. zend_jit_protect();
  4612. return SUCCESS;
  4613. }
  4614. ZEND_EXT_API void zend_jit_shutdown(void)
  4615. {
  4616. if (JIT_G(debug) & ZEND_JIT_DEBUG_SIZE) {
  4617. fprintf(stderr, "\nJIT memory usage: %td\n", (ptrdiff_t)((char*)*dasm_ptr - (char*)dasm_buf));
  4618. }
  4619. #ifdef HAVE_OPROFILE
  4620. if (JIT_G(debug) & ZEND_JIT_DEBUG_OPROFILE) {
  4621. zend_jit_oprofile_shutdown();
  4622. }
  4623. #endif
  4624. #ifdef HAVE_GDB
  4625. if (JIT_G(debug) & ZEND_JIT_DEBUG_GDB) {
  4626. zend_jit_gdb_unregister();
  4627. }
  4628. #endif
  4629. #ifdef HAVE_DISASM
  4630. zend_jit_disasm_shutdown();
  4631. #endif
  4632. #ifdef HAVE_PERFTOOLS
  4633. if (JIT_G(debug) & ZEND_JIT_DEBUG_PERF_DUMP) {
  4634. zend_jit_perf_jitdump_close();
  4635. }
  4636. #endif
  4637. if (JIT_G(exit_counters)) {
  4638. free(JIT_G(exit_counters));
  4639. }
  4640. }
  4641. static void zend_jit_reset_counters(void)
  4642. {
  4643. int i;
  4644. for (i = 0; i < ZEND_HOT_COUNTERS_COUNT; i++) {
  4645. zend_jit_hot_counters[i] = ZEND_JIT_COUNTER_INIT;
  4646. }
  4647. }
  4648. ZEND_EXT_API void zend_jit_activate(void)
  4649. {
  4650. zend_jit_profile_counter = 0;
  4651. if (JIT_G(on)) {
  4652. if (JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
  4653. zend_jit_reset_counters();
  4654. } else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
  4655. zend_jit_reset_counters();
  4656. zend_jit_trace_reset_caches();
  4657. }
  4658. }
  4659. }
  4660. ZEND_EXT_API void zend_jit_deactivate(void)
  4661. {
  4662. if (zend_jit_profile_counter) {
  4663. zend_class_entry *ce;
  4664. zend_shared_alloc_lock();
  4665. SHM_UNPROTECT();
  4666. zend_jit_unprotect();
  4667. zend_jit_check_funcs(EG(function_table), 0);
  4668. ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
  4669. if (ce->type == ZEND_INTERNAL_CLASS) {
  4670. break;
  4671. }
  4672. zend_jit_check_funcs(&ce->function_table, 1);
  4673. } ZEND_HASH_FOREACH_END();
  4674. zend_jit_protect();
  4675. SHM_PROTECT();
  4676. zend_shared_alloc_unlock();
  4677. zend_jit_profile_counter = 0;
  4678. }
  4679. }
  4680. static void zend_jit_restart_preloaded_op_array(zend_op_array *op_array)
  4681. {
  4682. zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
  4683. if (!func_info) {
  4684. return;
  4685. }
  4686. if (func_info->flags & ZEND_FUNC_JIT_ON_HOT_TRACE) {
  4687. zend_jit_restart_hot_trace_counters(op_array);
  4688. } else if (func_info->flags & ZEND_FUNC_JIT_ON_HOT_COUNTERS) {
  4689. zend_jit_restart_hot_counters(op_array);
  4690. #if 0
  4691. // TODO: We have to restore handlers for some inner basic-blocks, but we didn't store them ???
  4692. } else if (func_info->flags & (ZEND_FUNC_JIT_ON_FIRST_EXEC|ZEND_FUNC_JIT_ON_PROF_REQUEST)) {
  4693. zend_op *opline = op_array->opcodes;
  4694. zend_jit_op_array_extension *jit_extension =
  4695. (zend_jit_op_array_extension*)func_info;
  4696. if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
  4697. while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
  4698. opline++;
  4699. }
  4700. }
  4701. if (func_info->flags & ZEND_FUNC_JIT_ON_FIRST_EXEC) {
  4702. opline->handler = (const void*)zend_jit_runtime_jit_handler;
  4703. } else {
  4704. opline->handler = (const void*)zend_jit_profile_jit_handler;
  4705. }
  4706. #endif
  4707. }
  4708. }
  4709. static void zend_jit_restart_preloaded_script(zend_persistent_script *script)
  4710. {
  4711. zend_class_entry *ce;
  4712. zend_op_array *op_array;
  4713. zend_jit_restart_preloaded_op_array(&script->script.main_op_array);
  4714. ZEND_HASH_FOREACH_PTR(&script->script.function_table, op_array) {
  4715. zend_jit_restart_preloaded_op_array(op_array);
  4716. } ZEND_HASH_FOREACH_END();
  4717. ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
  4718. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  4719. if (op_array->type == ZEND_USER_FUNCTION) {
  4720. zend_jit_restart_preloaded_op_array(op_array);
  4721. }
  4722. } ZEND_HASH_FOREACH_END();
  4723. } ZEND_HASH_FOREACH_END();
  4724. }
  4725. ZEND_EXT_API void zend_jit_restart(void)
  4726. {
  4727. if (dasm_buf) {
  4728. zend_jit_unprotect();
  4729. #if ZEND_JIT_TARGET_ARM64
  4730. memset(dasm_labels_veneers, 0, sizeof(void*) * ZEND_MM_ALIGNED_SIZE_EX(zend_lb_MAX, DASM_ALIGNMENT));
  4731. #endif
  4732. /* restore JIT buffer pos */
  4733. dasm_ptr[0] = dasm_ptr[1];
  4734. zend_jit_trace_restart();
  4735. if (ZCSG(preload_script)) {
  4736. zend_jit_restart_preloaded_script(ZCSG(preload_script));
  4737. if (ZCSG(saved_scripts)) {
  4738. zend_persistent_script **p = ZCSG(saved_scripts);
  4739. while (*p) {
  4740. zend_jit_restart_preloaded_script(*p);
  4741. p++;
  4742. }
  4743. }
  4744. }
  4745. zend_jit_protect();
  4746. }
  4747. }
  4748. #endif /* HAVE_JIT */