Opnd.cpp 117 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. namespace IR
  7. {
  8. ///----------------------------------------------------------------------------
  9. ///
  10. /// Opnd::UseWithNewType
  11. ///
  12. /// Creates a Use (a copy if already in use or returns the same)
  13. /// and sets it type
  14. ///
  15. ///----------------------------------------------------------------------------
  16. Opnd*
  17. Opnd::UseWithNewType(IRType type, Func * func)
  18. {
  19. Opnd * res = this->Use(func);
  20. res->SetType(type);
  21. StackSym* sym = res->GetStackSym();
  22. if (sym)
  23. {
  24. if (TySize[sym->GetType()] < TySize[type])
  25. {
  26. Assert(!sym->IsAllocated());
  27. sym->m_type = type;
  28. }
  29. }
  30. return res;
  31. }
  32. bool
  33. Opnd::IsTaggedInt() const
  34. {
  35. return GetValueType().IsTaggedInt();
  36. }
  37. bool
  38. Opnd::IsTaggedValue() const
  39. {
  40. CompileAssert(!FLOATVAR || INT32VAR);
  41. #if FLOATVAR
  42. return GetValueType().IsNumber();
  43. #else
  44. return IsTaggedInt();
  45. #endif
  46. }
  47. bool
  48. Opnd::IsNotNumber() const
  49. {
  50. if (this->GetValueType().IsNotNumber())
  51. {
  52. return true;
  53. }
  54. if (this->IsRegOpnd())
  55. {
  56. const IR::RegOpnd* regOpnd = this->AsRegOpnd();
  57. if (regOpnd->m_sym == nullptr)
  58. {
  59. return true;
  60. }
  61. return regOpnd->m_sym->m_isNotNumber;
  62. }
  63. return false;
  64. }
  65. bool
  66. Opnd::IsNotInt() const
  67. {
  68. if (IsNotNumber() || IsFloat())
  69. {
  70. return true;
  71. }
  72. // Check if it's a definite type that cannot be a number
  73. if (GetValueType().IsDefinite() && !GetValueType().HasBeenNumber())
  74. {
  75. return true;
  76. }
  77. if (this->IsRegOpnd())
  78. {
  79. const IR::RegOpnd* reg = this->AsRegOpnd();
  80. // If the reg is const, it should be an int const
  81. return reg->m_sym->IsConst() && !reg->m_sym->IsIntConst();
  82. }
  83. return false;
  84. }
  85. bool
  86. Opnd::IsNotTaggedValue() const
  87. {
  88. if (!PHASE_OFF1(Js::OptTagChecksPhase) && this->GetValueType().IsNotTaggedValue())
  89. {
  90. return true;
  91. }
  92. return this->IsNotNumber();
  93. }
  94. bool
  95. Opnd::IsWriteBarrierTriggerableValue()
  96. {
  97. // Determines whether if an operand is used as a source in a store instruction, whether the store needs a write barrier
  98. // If it's a tagged value, we don't need a write barrier
  99. if (this->IsTaggedValue())
  100. {
  101. return false;
  102. }
  103. if (TySize[this->GetType()] != sizeof(void*))
  104. {
  105. return false;
  106. }
  107. #if DBG
  108. if (CONFIG_FLAG(ForceSoftwareWriteBarrier) && CONFIG_FLAG(VerifyBarrierBit))
  109. {
  110. return true; // No further optimization if we are in verification
  111. }
  112. #endif
  113. // If this operand is known address, then it doesn't need a write barrier, the address is either not a GC address or is pinned
  114. if (this->IsAddrOpnd() && this->AsAddrOpnd()->GetAddrOpndKind() == AddrOpndKindDynamicVar)
  115. {
  116. return false;
  117. }
  118. // If its null/boolean/undefined, we don't need a write barrier since the javascript library will keep those guys alive
  119. return !(this->GetValueType().IsBoolean() || this->GetValueType().IsNull() || this->GetValueType().IsUndefined());
  120. }
  121. /*
  122. * This is a devirtualized functions See the note above Opnd:Copy()
  123. */
  124. OpndKind Opnd::GetKind() const
  125. {
  126. return this->m_kind;
  127. }
  128. /*
  129. * This is a devirtualized functions See the note above Opnd:Copy()
  130. */
  131. Opnd *
  132. Opnd::CloneDef(Func *func)
  133. {
  134. switch (this->m_kind)
  135. {
  136. case OpndKindSym:
  137. if ((*static_cast<SymOpnd*>(this)).IsPropertySymOpnd())
  138. {
  139. return static_cast<PropertySymOpnd*>(this)->CloneDefInternalSub(func);
  140. }
  141. return static_cast<SymOpnd*>(this)->CloneDefInternal(func);
  142. case OpndKindReg:
  143. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  144. {
  145. return static_cast<ArrayRegOpnd*>(this)->CloneDefInternalSub(func);
  146. }
  147. return static_cast<RegOpnd*>(this)->CloneDefInternal(func);
  148. case OpndKindIndir:
  149. return static_cast<IndirOpnd*>(this)->CloneDefInternal(func);
  150. case OpndKindList:
  151. return static_cast<ListOpnd*>(this)->CloneDefInternal(func);
  152. default:
  153. return this->Copy(func);
  154. };
  155. }
  156. /*
  157. * This is a devirtualized functions See the note above Opnd:Copy()
  158. */
  159. Opnd *
  160. Opnd::CloneUse(Func *func)
  161. {
  162. switch (this->m_kind)
  163. {
  164. case OpndKindSym:
  165. if ((*static_cast<SymOpnd*>(this)).IsPropertySymOpnd())
  166. {
  167. return static_cast<PropertySymOpnd*>(this)->CloneUseInternalSub(func);
  168. }
  169. return static_cast<SymOpnd*>(this)->CloneUseInternal(func);
  170. case OpndKindReg:
  171. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  172. {
  173. return static_cast<ArrayRegOpnd*>(this)->CloneUseInternalSub(func);
  174. }
  175. return static_cast<RegOpnd*>(this)->CloneUseInternal(func);
  176. case OpndKindIndir:
  177. return static_cast<IndirOpnd*>(this)->CloneUseInternal(func);
  178. case OpndKindList:
  179. return static_cast<ListOpnd*>(this)->CloneUseInternal(func);
  180. default:
  181. return this->Copy(func);
  182. };
  183. }
  184. /*
  185. * This is a devirtualized functions See the note above Opnd:Copy()
  186. */
  187. void Opnd::Free(Func *func)
  188. {
  189. AssertMsg(!IsInUse(), "Attempting to free in use operand.");
  190. switch (this->m_kind)
  191. {
  192. case OpndKindIntConst:
  193. //NOTE: use to be Sealed do not do sub class checks like in CloneUse
  194. static_cast<IntConstOpnd*>(this)->FreeInternal(func);
  195. break;
  196. case OpndKindInt64Const:
  197. return static_cast<Int64ConstOpnd*>(this)->FreeInternal(func);
  198. case OpndKindSimd128Const:
  199. static_cast<Simd128ConstOpnd*>(this)->FreeInternal(func);
  200. break;
  201. case OpndKindFloatConst:
  202. static_cast<FloatConstOpnd*>(this)->FreeInternal(func);
  203. break;
  204. case OpndKindFloat32Const:
  205. static_cast<Float32ConstOpnd*>(this)->FreeInternal(func);
  206. break;
  207. case OpndKindHelperCall:
  208. static_cast<HelperCallOpnd*>(this)->FreeInternal(func);
  209. break;
  210. case OpndKindSym:
  211. static_cast<SymOpnd*>(this)->FreeInternal(func);
  212. break;
  213. case OpndKindReg:
  214. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  215. {
  216. static_cast<ArrayRegOpnd*>(this)->FreeInternalSub(func);
  217. break;
  218. }
  219. static_cast<RegOpnd*>(this)->FreeInternal(func);
  220. break;
  221. case OpndKindAddr:
  222. static_cast<AddrOpnd*>(this)->FreeInternal(func);
  223. break;
  224. case OpndKindIndir:
  225. static_cast<IndirOpnd*>(this)->FreeInternal(func);
  226. break;
  227. case OpndKindList:
  228. static_cast<ListOpnd*>(this)->FreeInternal(func);
  229. break;
  230. case OpndKindMemRef:
  231. static_cast<MemRefOpnd*>(this)->FreeInternal(func);
  232. break;
  233. case OpndKindLabel:
  234. static_cast<LabelOpnd*>(this)->FreeInternal(func);
  235. break;
  236. case OpndKindRegBV:
  237. static_cast<RegBVOpnd*>(this)->FreeInternal(func);
  238. break;
  239. default:
  240. Assert(UNREACHED);
  241. __assume(UNREACHED);
  242. };
  243. #if DBG
  244. if (func->m_alloc->HasDelayFreeList())
  245. {
  246. this->isDeleted = true;
  247. }
  248. #endif
  249. }
  250. /*
  251. * This is a devirtualized functions See the note above Opnd:Copy()
  252. */
  253. bool Opnd::IsEqual(Opnd *opnd)
  254. {
  255. switch (this->m_kind)
  256. {
  257. case OpndKindIntConst:
  258. return static_cast<IntConstOpnd*>(this)->IsEqualInternal(opnd);
  259. case OpndKindInt64Const:
  260. return static_cast<Int64ConstOpnd*>(this)->IsEqualInternal(opnd);
  261. case OpndKindFloatConst:
  262. return static_cast<FloatConstOpnd*>(this)->IsEqualInternal(opnd);
  263. case OpndKindFloat32Const:
  264. return static_cast<Float32ConstOpnd*>(this)->IsEqualInternal(opnd);
  265. case OpndKindHelperCall:
  266. if ((*static_cast<HelperCallOpnd*>(this)).IsDiagHelperCallOpnd())
  267. {
  268. return static_cast<DiagHelperCallOpnd*>(this)->IsEqualInternalSub(opnd);
  269. }
  270. return static_cast<HelperCallOpnd*>(this)->IsEqualInternal(opnd);
  271. case OpndKindSym:
  272. //NOTE: use to be Sealed do not do sub class checks like in CloneUse
  273. return static_cast<SymOpnd*>(this)->IsEqualInternal(opnd);
  274. case OpndKindReg:
  275. //NOTE: not sealed but ArrayRegOpnd::isEqual function does not exist, default to RegOpnd only
  276. return static_cast<RegOpnd*>(this)->IsEqualInternal(opnd);
  277. case OpndKindAddr:
  278. return static_cast<AddrOpnd*>(this)->IsEqualInternal(opnd);
  279. case OpndKindIndir:
  280. return static_cast<IndirOpnd*>(this)->IsEqualInternal(opnd);
  281. case OpndKindList:
  282. return static_cast<ListOpnd*>(this)->IsEqualInternal(opnd);
  283. case OpndKindMemRef:
  284. return static_cast<MemRefOpnd*>(this)->IsEqualInternal(opnd);
  285. case OpndKindLabel:
  286. return static_cast<LabelOpnd*>(this)->IsEqualInternal(opnd);
  287. case OpndKindRegBV:
  288. return static_cast<RegBVOpnd*>(this)->IsEqualInternal(opnd);
  289. default:
  290. Assert(UNREACHED);
  291. __assume(UNREACHED);
  292. };
  293. }
  294. /*
  295. * This is a devirtualized functions If you inherit from any of the child classes of Opnd
  296. * And would like to override the default method behavior you must add an
  297. * Is<your new Opnd Type>Opnd() call and check for it like in examples
  298. * HelperCallOpnd, PropertySymOpnd, & RegOpnd
  299. */
  300. Opnd * Opnd::Copy(Func *func)
  301. {
  302. switch (this->m_kind)
  303. {
  304. case OpndKindIntConst:
  305. return static_cast<IntConstOpnd*>(this)->CopyInternal(func);
  306. case OpndKindInt64Const:
  307. return static_cast<Int64ConstOpnd*>(this)->CopyInternal(func);
  308. case OpndKindFloatConst:
  309. return static_cast<FloatConstOpnd*>(this)->CopyInternal(func);
  310. case OpndKindHelperCall:
  311. if ((*static_cast<HelperCallOpnd*>(this)).IsDiagHelperCallOpnd())
  312. {
  313. return static_cast<DiagHelperCallOpnd*>(this)->CopyInternalSub(func);
  314. }
  315. return static_cast<HelperCallOpnd*>(this)->CopyInternal(func);
  316. case OpndKindSym:
  317. if ((*static_cast<SymOpnd*>(this)).IsPropertySymOpnd())
  318. {
  319. return static_cast<PropertySymOpnd*>(this)->CopyInternalSub(func);
  320. }
  321. return static_cast<SymOpnd*>(this)->CopyInternal(func);
  322. case OpndKindReg:
  323. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  324. {
  325. return static_cast<ArrayRegOpnd*>(this)->CopyInternalSub(func);
  326. }
  327. return static_cast<RegOpnd*>(this)->CopyInternal(func);
  328. case OpndKindAddr:
  329. return static_cast<AddrOpnd*>(this)->CopyInternal(func);
  330. case OpndKindIndir:
  331. return static_cast<IndirOpnd*>(this)->CopyInternal(func);
  332. case OpndKindList:
  333. return static_cast<ListOpnd*>(this)->CopyInternal(func);
  334. case OpndKindMemRef:
  335. return static_cast<MemRefOpnd*>(this)->CopyInternal(func);
  336. case OpndKindLabel:
  337. return static_cast<LabelOpnd*>(this)->CopyInternal(func);
  338. case OpndKindRegBV:
  339. return static_cast<RegBVOpnd*>(this)->CopyInternal(func);
  340. default:
  341. Assert(UNREACHED);
  342. __assume(UNREACHED);
  343. };
  344. }
  345. StackSym *
  346. Opnd::GetStackSym() const
  347. {
  348. switch (this->GetKind())
  349. {
  350. case OpndKindSym:
  351. return static_cast<SymOpnd const *>(this)->GetStackSymInternal();
  352. case OpndKindReg:
  353. return static_cast<RegOpnd const *>(this)->GetStackSymInternal();
  354. default:
  355. return nullptr;
  356. }
  357. }
  358. Sym*
  359. Opnd::GetSym() const
  360. {
  361. switch (this->GetKind())
  362. {
  363. case OpndKindSym:
  364. return static_cast<SymOpnd const *>(this)->m_sym;
  365. case OpndKindReg:
  366. return static_cast<RegOpnd const *>(this)->m_sym;
  367. default:
  368. return nullptr;
  369. }
  370. }
  371. int64
  372. Opnd::GetImmediateValue(Func* func)
  373. {
  374. switch (this->GetKind())
  375. {
  376. case OpndKindIntConst:
  377. return this->AsIntConstOpnd()->GetValue();
  378. case OpndKindInt64Const:
  379. return this->AsInt64ConstOpnd()->GetValue();
  380. case OpndKindAddr:
  381. return (intptr_t)this->AsAddrOpnd()->m_address;
  382. case OpndKindHelperCall:
  383. return (intptr_t)IR::GetMethodAddress(func->GetThreadContextInfo(), this->AsHelperCallOpnd());
  384. default:
  385. AssertMsg(UNREACHED, "Unexpected immediate opnd kind");
  386. return 0;
  387. }
  388. }
  389. #if defined(_M_ARM)
  390. int32
  391. Opnd::GetImmediateValueAsInt32(Func * func)
  392. {
  393. Assert(!IRType_IsInt64(this->GetType()));
  394. Assert(this->GetKind() != OpndKindInt64Const);
  395. return (int32)this->GetImmediateValue(func);
  396. }
  397. #endif
  398. BailoutConstantValue Opnd::GetConstValue()
  399. {
  400. BailoutConstantValue value;
  401. if (this->IsIntConstOpnd())
  402. {
  403. value.InitIntConstValue(this->AsIntConstOpnd()->GetValue(), this->m_type);
  404. }
  405. else if (this->IsFloatConstOpnd())
  406. {
  407. value.InitFloatConstValue(this->AsFloatConstOpnd()->m_value);
  408. }
  409. else
  410. {
  411. AssertMsg(this->IsAddrOpnd(), "Unexpected const sym");
  412. value.InitVarConstValue(this->AsAddrOpnd()->m_address);
  413. }
  414. return value;
  415. }
  416. void Opnd::SetValueType(const ValueType valueType)
  417. {
  418. if(m_isValueTypeFixed)
  419. {
  420. return;
  421. }
  422. // ArrayRegOpnd has information specific to the array type, so make sure that doesn't change
  423. Assert(
  424. !IsRegOpnd() ||
  425. !AsRegOpnd()->IsArrayRegOpnd() ||
  426. valueType.IsObject() && valueType.GetObjectType() == m_valueType.GetObjectType());
  427. m_valueType = valueType;
  428. }
  429. bool Opnd::IsScopeObjOpnd(Func * func)
  430. {
  431. if (IsRegOpnd())
  432. {
  433. return this->GetStackSym() == func->GetScopeObjSym();
  434. }
  435. else if(IsSymOpnd() && AsSymOpnd()->m_sym->IsPropertySym())
  436. {
  437. return this->AsSymOpnd()->m_sym->AsPropertySym()->m_stackSym == func->GetScopeObjSym();
  438. }
  439. return false;
  440. }
  441. ValueType Opnd::FindProfiledValueType()
  442. {
  443. if (!this->GetValueType().IsUninitialized())
  444. {
  445. return this->GetValueType();
  446. }
  447. // could be expanded to cover additional opnd kinds as well.
  448. if (this->IsRegOpnd() && this->AsRegOpnd()->m_sym->IsSingleDef())
  449. {
  450. IR::Instr * defInstr = this->AsRegOpnd()->m_sym->GetInstrDef();
  451. IR::Opnd * src1 = defInstr->GetSrc1();
  452. while(defInstr->m_opcode == Js::OpCode::Ld_A)
  453. {
  454. if (!src1->IsRegOpnd() || !src1->AsRegOpnd()->m_sym->IsSingleDef())
  455. {
  456. return ValueType::Uninitialized;
  457. }
  458. defInstr = src1->AsRegOpnd()->m_sym->GetInstrDef();
  459. src1 = defInstr->GetSrc1();
  460. }
  461. if (defInstr->GetDst()->GetValueType().IsAnyArray())
  462. {
  463. return defInstr->GetDst()->GetValueType().ToLikely();
  464. }
  465. else
  466. {
  467. return defInstr->GetDst()->GetValueType();
  468. }
  469. }
  470. return ValueType::Uninitialized;
  471. }
  472. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  473. void Opnd::DumpValueType()
  474. {
  475. if(m_valueType.IsUninitialized())
  476. {
  477. return;
  478. }
  479. if(!CONFIG_FLAG(Verbose))
  480. {
  481. // Skip printing the value type when it's obvious since verbose mode is off
  482. switch(this->GetKind())
  483. {
  484. case OpndKindIntConst:
  485. case OpndKindInt64Const:
  486. case OpndKindFloatConst:
  487. return;
  488. case OpndKindReg:
  489. {
  490. StackSym *const sym = this->AsRegOpnd()->m_sym;
  491. if(sym && (
  492. sym->IsInt32() ||
  493. sym->IsFloat32() ||
  494. sym->IsFloat64() ||
  495. sym->IsInt64() ||
  496. sym->IsUint64()
  497. ))
  498. {
  499. return;
  500. }
  501. break;
  502. }
  503. case OpndKindAddr:
  504. if(this->AsAddrOpnd()->m_address && this->AsAddrOpnd()->IsVar())
  505. {
  506. IR::AddrOpnd *addrOpnd = this->AsAddrOpnd();
  507. Js::Var address = addrOpnd->decodedValue ? addrOpnd->decodedValue : addrOpnd->m_address;
  508. // Tagged int might be encoded here, so check the type
  509. if (addrOpnd->GetAddrOpndKind() == AddrOpndKindConstantVar
  510. || Js::TaggedInt::Is(address) || (
  511. #if !FLOATVAR
  512. !JITManager::GetJITManager()->IsOOPJITEnabled() &&
  513. #endif
  514. Js::JavascriptNumber::Is_NoTaggedIntCheck(address)))
  515. {
  516. return;
  517. }
  518. }
  519. break;
  520. }
  521. }
  522. DumpValueType(m_valueType);
  523. }
  524. void Opnd::DumpValueType(const ValueType valueType)
  525. {
  526. if(valueType.IsUninitialized())
  527. {
  528. return;
  529. }
  530. char valueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
  531. valueType.ToString(valueTypeStr);
  532. Output::Print(_u("[%S]"), valueTypeStr);
  533. }
  534. #endif
  535. IntConstOpnd *Opnd::CreateUint32Opnd(const uint i, Func *const func)
  536. {
  537. return IntConstOpnd::New(i, TyUint32, func, true);
  538. }
  539. IntConstOpnd *Opnd::CreateProfileIdOpnd(const Js::ProfileId profileId, Func *const func)
  540. {
  541. CompileAssert(sizeof(profileId) == sizeof(uint16));
  542. return IntConstOpnd::New(profileId, TyUint16, func, true);
  543. }
  544. IntConstOpnd *Opnd::CreateInlineCacheIndexOpnd(const Js::InlineCacheIndex inlineCacheIndex, Func *const func)
  545. {
  546. CompileAssert(sizeof(inlineCacheIndex) == sizeof(uint));
  547. return CreateUint32Opnd(inlineCacheIndex, func);
  548. }
  549. RegOpnd *Opnd::CreateFramePointerOpnd(Func *const func)
  550. {
  551. return RegOpnd::New(nullptr, LowererMD::GetRegFramePointer(), TyMachPtr, func);
  552. }
  553. ///----------------------------------------------------------------------------
  554. ///
  555. /// SymOpnd::New
  556. ///
  557. /// Creates a new SymOpnd.
  558. ///
  559. ///----------------------------------------------------------------------------
  560. SymOpnd *
  561. SymOpnd::New(Sym *sym, IRType type, Func *func)
  562. {
  563. return SymOpnd::New(sym, 0, type, func);
  564. }
  565. SymOpnd *
  566. SymOpnd::New(Sym *sym, uint32 offset, IRType type, Func *func)
  567. {
  568. SymOpnd * symOpnd;
  569. AssertMsg(sym, "A SymOpnd needs a valid symbol.");
  570. symOpnd = JitAnew(func->m_alloc, IR::SymOpnd);
  571. symOpnd->m_sym = sym;
  572. symOpnd->m_offset = offset;
  573. symOpnd->m_type = type;
  574. symOpnd->SetIsJITOptimizedReg(false);
  575. symOpnd->m_kind = OpndKindSym;
  576. return symOpnd;
  577. }
  578. ///----------------------------------------------------------------------------
  579. ///
  580. /// SymOpnd::Copy
  581. ///
  582. /// Returns a copy of this opnd.
  583. ///
  584. ///----------------------------------------------------------------------------
  585. SymOpnd *
  586. SymOpnd::CopyInternal(Func *func)
  587. {
  588. Assert(m_kind == OpndKindSym);
  589. SymOpnd * newOpnd;
  590. newOpnd = SymOpnd::New(m_sym, m_offset, m_type, func);
  591. newOpnd->m_valueType = m_valueType;
  592. newOpnd->canStoreTemp = this->canStoreTemp;
  593. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  594. return newOpnd;
  595. }
  596. SymOpnd *
  597. SymOpnd::CloneDefInternal(Func *func)
  598. {
  599. Assert(m_kind == OpndKindSym);
  600. Sym *sym = this->m_sym;
  601. if (sym->IsStackSym() && sym->AsStackSym()->m_isSingleDef)
  602. {
  603. StackSym * oldSym = sym->AsStackSym();
  604. StackSym * newSym = oldSym->CloneDef(func)->AsStackSym();
  605. if (func->GetCloner()->clonedInstrGetOrigArgSlotSym && oldSym->IsArgSlotSym())
  606. {
  607. Assert(newSym != oldSym);
  608. this->m_sym = newSym;
  609. newSym->m_instrDef = oldSym->m_instrDef;
  610. oldSym->m_instrDef = nullptr;
  611. sym = oldSym;
  612. }
  613. else
  614. {
  615. sym = newSym;
  616. }
  617. }
  618. SymOpnd * newOpnd = SymOpnd::New(sym, m_offset, m_type, func);
  619. return newOpnd;
  620. }
  621. SymOpnd *
  622. SymOpnd::CloneUseInternal(Func *func)
  623. {
  624. Assert(m_kind == OpndKindSym);
  625. Sym *sym = this->m_sym;
  626. if (sym->IsStackSym() && sym->AsStackSym()->m_isSingleDef)
  627. {
  628. StackSym * oldSym = sym->AsStackSym();
  629. StackSym * newSym = oldSym->CloneUse(func)->AsStackSym();
  630. if (func->GetCloner()->clonedInstrGetOrigArgSlotSym && oldSym->IsArgSlotSym())
  631. {
  632. Assert(newSym != oldSym);
  633. this->m_sym = newSym;
  634. sym = oldSym;
  635. }
  636. else
  637. {
  638. sym = newSym;
  639. }
  640. }
  641. SymOpnd * newOpnd = SymOpnd::New(sym, m_offset, m_type, func);
  642. return newOpnd;
  643. }
  644. StackSym *
  645. SymOpnd::GetStackSymInternal() const
  646. {
  647. return (this->m_sym && this->m_sym->IsStackSym()) ? this->m_sym->AsStackSym() : nullptr;
  648. }
  649. ///----------------------------------------------------------------------------
  650. ///
  651. /// SymOpnd::IsEqual
  652. /// The SymOpnd's offset is 0 if it is called before regalloc. For Stack symopnd,
  653. /// compare the type and symbol's offsets only when the symbol's isAllocated is true.
  654. /// For other cases, compare the type, syms and offsets.
  655. /// For example, following two instructions after RegAlloc phase:
  656. /// iarg65535(s534)<0>.i32 = MOV (NULL).var
  657. /// iarg65535(s533)<0>.i32 = MOV (NULL).var
  658. /// are actually same instructions after encoding: mov dword ptr[ebp-0x1c], 0x0
  659. /// Here for dst stack symOpnd, m_sym are different: s534 vs. s533, but offsets and
  660. /// types are the same. So this function will report true if isAllocated is true.
  661. /// Note: for property symopnd, still compare type, offset and sym.
  662. ///
  663. ///----------------------------------------------------------------------------
  664. bool
  665. SymOpnd::IsEqualInternal(Opnd *opnd)
  666. {
  667. Assert(m_kind == OpndKindSym);
  668. Assert(opnd);
  669. if (!opnd->IsSymOpnd() || this->GetType() != opnd->GetType())
  670. {
  671. return false;
  672. }
  673. SymOpnd *opndSym = opnd->AsSymOpnd();
  674. Assert(opndSym);
  675. StackSym *thisStackSym = this->GetStackSymInternal();
  676. StackSym *opndStackSym = opndSym->GetStackSymInternal();
  677. if (thisStackSym && opndStackSym && thisStackSym->IsAllocated() && opndStackSym->IsAllocated())
  678. {
  679. return thisStackSym->m_offset == opndStackSym->m_offset;
  680. }
  681. else
  682. {
  683. return m_sym == opndSym->m_sym && m_offset == opndSym->m_offset;
  684. }
  685. }
  686. void
  687. SymOpnd::FreeInternal(Func *func)
  688. {
  689. Assert(m_kind == OpndKindSym);
  690. JitAdelete(func->m_alloc, this);
  691. }
  692. RegOpnd *SymOpnd::CreatePropertyOwnerOpnd(Func *const func) const
  693. {
  694. Assert(m_sym->IsPropertySym());
  695. Assert(func);
  696. StackSym *const propertyOwnerSym = m_sym->AsPropertySym()->m_stackSym;
  697. RegOpnd *const propertyOwnerOpnd = RegOpnd::New(propertyOwnerSym, propertyOwnerSym->GetType(), func);
  698. propertyOwnerOpnd->SetValueType(GetPropertyOwnerValueType());
  699. return propertyOwnerOpnd;
  700. }
  701. PropertySymOpnd *
  702. PropertySymOpnd::New(PropertySym *propertySym, uint inlineCacheIndex, IRType type, Func *func)
  703. {
  704. PropertySymOpnd *newOpnd = IR::PropertySymOpnd::New(propertySym, type, func);
  705. newOpnd->Init(inlineCacheIndex, func);
  706. return newOpnd;
  707. }
  708. void
  709. PropertySymOpnd::Init(uint inlineCacheIndex, Func *func)
  710. {
  711. this->Init(inlineCacheIndex,
  712. inlineCacheIndex != -1 ? func->GetRuntimeInlineCache(inlineCacheIndex) : 0,
  713. inlineCacheIndex != -1 ? func->GetRuntimePolymorphicInlineCache(inlineCacheIndex) : nullptr,
  714. inlineCacheIndex != -1 ? func->GetObjTypeSpecFldInfo(inlineCacheIndex) : nullptr,
  715. inlineCacheIndex != -1 ? func->GetPolyCacheUtilToInitialize(inlineCacheIndex) : PolymorphicInlineCacheUtilizationMinValue);
  716. }
  717. PropertySymOpnd *
  718. PropertySymOpnd::New(PropertySym *propertySym, IRType type, Func *func)
  719. {
  720. PropertySymOpnd *newOpnd = JitAnew(func->m_alloc, IR::PropertySymOpnd);
  721. newOpnd->m_sym = propertySym;
  722. newOpnd->m_offset = 0;
  723. newOpnd->m_type = type;
  724. newOpnd->SetObjTypeSpecFldInfo(nullptr);
  725. newOpnd->finalType = JITTypeHolder(nullptr);
  726. newOpnd->monoGuardType = JITTypeHolder(nullptr);
  727. newOpnd->guardedPropOps = nullptr;
  728. newOpnd->writeGuards = nullptr;
  729. newOpnd->objTypeSpecFlags = 0;
  730. newOpnd->isPropertySymOpnd = true;
  731. newOpnd->checkedTypeSetIndex = (uint16)-1;
  732. newOpnd->m_kind = OpndKindSym;
  733. return newOpnd;
  734. }
  735. void
  736. PropertySymOpnd::Init(uint inlineCacheIndex, intptr_t runtimeInlineCache, JITTimePolymorphicInlineCache * runtimePolymorphicInlineCache, ObjTypeSpecFldInfo* objTypeSpecFldInfo, byte polyCacheUtil)
  737. {
  738. this->m_inlineCacheIndex = inlineCacheIndex;
  739. this->m_runtimeInlineCache = runtimeInlineCache;
  740. this->m_runtimePolymorphicInlineCache = runtimePolymorphicInlineCache;
  741. this->m_polyCacheUtil = polyCacheUtil;
  742. this->SetObjTypeSpecFldInfo(objTypeSpecFldInfo);
  743. this->SetIsJITOptimizedReg(false);
  744. }
  745. PropertySymOpnd *
  746. PropertySymOpnd::CopyCommon(Func *func)
  747. {
  748. PropertySymOpnd *newOpnd = PropertySymOpnd::New(this->m_sym->AsPropertySym(), this->m_type, func);
  749. newOpnd->m_valueType = this->m_valueType;
  750. newOpnd->m_inlineCacheIndex = this->m_inlineCacheIndex;
  751. newOpnd->m_runtimeInlineCache = this->m_runtimeInlineCache;
  752. newOpnd->m_runtimePolymorphicInlineCache = this->m_runtimePolymorphicInlineCache;
  753. newOpnd->canStoreTemp = this->canStoreTemp;
  754. return newOpnd;
  755. }
  756. PropertySymOpnd *
  757. PropertySymOpnd::CopyWithoutFlowSensitiveInfo(Func *func)
  758. {
  759. PropertySymOpnd *newOpnd = CopyCommon(func);
  760. newOpnd->SetObjTypeSpecFldInfo(this->objTypeSpecFldInfo);
  761. // This field is not flow sensitive. It is only on if the instruction is CheckFixedMethodFld. If we ever
  762. // hoist CheckFixedMethodFld (or otherwise copy it), we must make sure not to change the opcode.
  763. newOpnd->usesFixedValue = this->usesFixedValue;
  764. // Note that the following fields are flow sensitive. If we're cloning this operand in order to attach it to
  765. // an instruction elsewhere in the flow (e.g. field hoisting or copy propagation), these fields cannot be copied.
  766. // If the caller knows some of them can be safely copied, the caller must do so manually.
  767. Assert(newOpnd->typeCheckSeqFlags == 0);
  768. Assert(newOpnd->finalType == nullptr);
  769. Assert(newOpnd->guardedPropOps == nullptr);
  770. Assert(newOpnd->writeGuards == nullptr);
  771. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  772. return newOpnd;
  773. }
  774. PropertySymOpnd *
  775. PropertySymOpnd::CopyInternalSub(Func *func)
  776. {
  777. Assert(m_kind == OpndKindSym && this->IsPropertySymOpnd());
  778. PropertySymOpnd *newOpnd = CopyCommon(func);
  779. newOpnd->objTypeSpecFldInfo = this->objTypeSpecFldInfo;
  780. newOpnd->usesAuxSlot = usesAuxSlot;
  781. newOpnd->slotIndex = slotIndex;
  782. newOpnd->checkedTypeSetIndex = checkedTypeSetIndex;
  783. newOpnd->objTypeSpecFlags = this->objTypeSpecFlags;
  784. newOpnd->finalType = this->finalType;
  785. newOpnd->guardedPropOps = this->guardedPropOps != nullptr ? this->guardedPropOps->CopyNew() : nullptr;
  786. newOpnd->writeGuards = this->writeGuards != nullptr ? this->writeGuards->CopyNew() : nullptr;
  787. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  788. return newOpnd;
  789. }
  790. bool
  791. PropertySymOpnd::IsObjectHeaderInlined() const
  792. {
  793. JITTypeHolder type(nullptr);
  794. if (this->IsMono())
  795. {
  796. type = this->GetType();
  797. }
  798. else if (this->HasEquivalentTypeSet())
  799. {
  800. type = this->GetFirstEquivalentType();
  801. }
  802. if (type != nullptr && Js::DynamicType::Is(type->GetTypeId()))
  803. {
  804. return type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler();
  805. }
  806. return false;
  807. }
  808. bool
  809. PropertySymOpnd::ChangesObjectLayout() const
  810. {
  811. JITTypeHolder cachedType = this->HasInitialType() ? this->GetInitialType() :
  812. this->IsMono() ? this->GetType() : this->GetFirstEquivalentType();
  813. JITTypeHolder finalType = this->GetFinalType();
  814. if (finalType != nullptr && Js::DynamicType::Is(finalType->GetTypeId()))
  815. {
  816. // This is the case where final type opt may cause pro-active type transition to take place.
  817. Assert(cachedType != nullptr && Js::DynamicType::Is(cachedType->GetTypeId()));
  818. return cachedType->GetTypeHandler()->GetInlineSlotCapacity() != finalType->GetTypeHandler()->GetInlineSlotCapacity() ||
  819. cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() != finalType->GetTypeHandler()->GetOffsetOfInlineSlots();
  820. }
  821. if (!this->HasInitialType())
  822. {
  823. return false;
  824. }
  825. JITTypeHolder initialType = this->GetInitialType();
  826. if (initialType != nullptr && Js::DynamicType::Is(initialType->GetTypeId()))
  827. {
  828. // This is the case where the type transition actually occurs. (This is the only case that's detectable
  829. // during the loop pre-pass, since final types are not in place yet.)
  830. const JITTypeHandler * initialTypeHandler = initialType->GetTypeHandler();
  831. // If no final type has been set in the forward pass, then we have no way of knowing how the object shape will evolve here.
  832. // If the initial type is object-header-inlined, assume that the layout may change.
  833. return initialTypeHandler->IsObjectHeaderInlinedTypeHandler();
  834. }
  835. return false;
  836. }
  837. void
  838. PropertySymOpnd::UpdateSlotForFinalType()
  839. {
  840. JITTypeHolder finalType = this->GetFinalType();
  841. Assert(this->IsMono() || this->checkedTypeSetIndex != (uint16)-1);
  842. JITTypeHolder cachedType =
  843. this->IsMono() ? this->GetType() : this->GetEquivalentTypeSet()->GetType(checkedTypeSetIndex);
  844. Assert(finalType != nullptr && Js::DynamicType::Is(finalType->GetTypeId()));
  845. Assert(cachedType != nullptr && Js::DynamicType::Is(cachedType->GetTypeId()));
  846. if (finalType == cachedType)
  847. {
  848. return;
  849. }
  850. // TODO: OOP JIT: should assert about runtime type handler addr
  851. Assert(cachedType->GetTypeHandler() != finalType->GetTypeHandler());
  852. if (cachedType->GetTypeHandler()->GetInlineSlotCapacity() == finalType->GetTypeHandler()->GetInlineSlotCapacity() &&
  853. cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() == finalType->GetTypeHandler()->GetOffsetOfInlineSlots())
  854. {
  855. // Nothing can change, since the variables aren't changing.
  856. return;
  857. }
  858. // Get the slot index and figure out the property index
  859. uint16 index = this->GetSlotIndex();
  860. if (this->UsesAuxSlot())
  861. {
  862. index += cachedType->GetTypeHandler()->GetInlineSlotCapacity();
  863. }
  864. else
  865. {
  866. index -= cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() / sizeof(Js::Var);
  867. }
  868. // Figure out the slot index and aux-ness from the property index
  869. if (index >= finalType->GetTypeHandler()->GetInlineSlotCapacity())
  870. {
  871. this->SetUsesAuxSlot(true);
  872. index -= finalType->GetTypeHandler()->GetInlineSlotCapacity();
  873. }
  874. else
  875. {
  876. this->SetUsesAuxSlot(false);
  877. index += finalType->GetTypeHandler()->GetOffsetOfInlineSlots() / sizeof(Js::Var);
  878. }
  879. this->SetSlotIndex(index);
  880. }
  881. bool PropertySymOpnd::HasFinalType() const
  882. {
  883. return this->finalType != nullptr;
  884. }
  885. bool PropertySymOpnd::NeedsAuxSlotPtrSymLoad() const
  886. {
  887. // Consider: reload based on guarded prop ops' use of aux slots
  888. return this->GetAuxSlotPtrSym() != nullptr;
  889. }
  890. void PropertySymOpnd::GenerateAuxSlotPtrSymLoad(IR::Instr * instrInsert)
  891. {
  892. StackSym * auxSlotPtrSym = GetAuxSlotPtrSym();
  893. Assert(auxSlotPtrSym);
  894. Func * func = instrInsert->m_func;
  895. IR::Opnd *opndIndir = IR::IndirOpnd::New(this->CreatePropertyOwnerOpnd(func), Js::DynamicObject::GetOffsetOfAuxSlots(), TyMachReg, func);
  896. IR::RegOpnd *regOpnd = IR::RegOpnd::New(auxSlotPtrSym, TyMachReg, func);
  897. regOpnd->SetIsJITOptimizedReg(true);
  898. Lowerer::InsertMove(regOpnd, opndIndir, instrInsert);
  899. }
  900. PropertySymOpnd *
  901. PropertySymOpnd::CloneDefInternalSub(Func *func)
  902. {
  903. return this->CopyInternalSub(func);
  904. }
  905. PropertySymOpnd *
  906. PropertySymOpnd::CloneUseInternalSub(Func *func)
  907. {
  908. return this->CopyInternalSub(func);
  909. }
  910. bool
  911. PropertySymOpnd::ShouldUsePolyEquivTypeGuard(Func *const func) const
  912. {
  913. return this->IsPoly() && this->m_polyCacheUtil >= PolymorphicInlineCacheUtilizationThreshold && !PHASE_OFF(Js::PolyEquivTypeGuardPhase, func);
  914. }
  915. RegOpnd::RegOpnd(StackSym *sym, RegNum reg, IRType type)
  916. {
  917. Initialize(sym, reg, type);
  918. }
  919. RegOpnd::RegOpnd(const RegOpnd &other, StackSym *const sym)
  920. {
  921. Initialize(sym, other.m_reg, other.m_type);
  922. m_valueType = other.m_valueType;
  923. SetIsJITOptimizedReg(other.GetIsJITOptimizedReg());
  924. m_dontDeadStore = other.m_dontDeadStore;
  925. m_wasNegativeZeroPreventedByBailout = other.m_wasNegativeZeroPreventedByBailout;
  926. #if DBG
  927. m_symValueFrozen = other.m_symValueFrozen;
  928. #endif
  929. }
  930. void RegOpnd::Initialize(StackSym *sym, RegNum reg, IRType type)
  931. {
  932. AssertMsg(sym || reg != RegNOREG, "A RegOpnd needs a valid symbol or register.");
  933. Assert(!sym || sym->GetType() != TyMisc);
  934. m_kind = OpndKindReg;
  935. m_sym = sym;
  936. SetReg(reg);
  937. m_type = type;
  938. m_isTempLastUse = false;
  939. m_isCallArg = false;
  940. SetIsJITOptimizedReg(false);
  941. m_dontDeadStore = false;
  942. m_fgPeepTmp = false;
  943. m_wasNegativeZeroPreventedByBailout = false;
  944. m_isArrayRegOpnd = false;
  945. #if DBG
  946. m_symValueFrozen = false;
  947. #endif
  948. }
  949. ///----------------------------------------------------------------------------
  950. ///
  951. /// RegOpnd::New
  952. ///
  953. /// Creates a new RegOpnd.
  954. ///
  955. ///----------------------------------------------------------------------------
  956. RegOpnd *
  957. RegOpnd::New(IRType type, Func *func)
  958. {
  959. return RegOpnd::New(StackSym::New(type, func), RegNOREG, type, func);
  960. }
  961. IR::RegOpnd *
  962. RegOpnd::New(RegNum reg, IRType type, Func *func)
  963. {
  964. return RegOpnd::New(StackSym::New(type, func), reg, type, func);
  965. }
  966. RegOpnd *
  967. RegOpnd::New(StackSym *sym, IRType type, Func *func)
  968. {
  969. return RegOpnd::New(sym, RegNOREG, type, func);
  970. }
  971. RegOpnd *
  972. RegOpnd::New(StackSym *sym, RegNum reg, IRType type, Func *func)
  973. {
  974. return JitAnew(func->m_alloc, IR::RegOpnd, sym, reg, type);
  975. }
  976. ///----------------------------------------------------------------------------
  977. ///
  978. /// RegOpnd::Copy
  979. ///
  980. /// Returns a copy of this opnd.
  981. ///
  982. ///----------------------------------------------------------------------------
  983. RegOpnd *
  984. RegOpnd::CopyInternal(StackSym * sym, Func *func)
  985. {
  986. Assert(m_kind == OpndKindReg);
  987. return JitAnew(func->m_alloc, IR::RegOpnd, *this, sym);
  988. }
  989. RegOpnd *
  990. RegOpnd::CopyInternal(Func *func)
  991. {
  992. return CopyInternal(m_sym, func);
  993. }
  994. RegOpnd *
  995. RegOpnd::CloneDefInternal(Func *func)
  996. {
  997. StackSym * sym = m_sym ? m_sym->CloneDef(func) : nullptr;
  998. return CopyInternal(sym, func);
  999. }
  1000. RegOpnd *
  1001. RegOpnd::CloneUseInternal(Func *func)
  1002. {
  1003. StackSym * sym = m_sym ? m_sym->CloneUse(func) : nullptr;
  1004. return CopyInternal(sym, func);
  1005. }
  1006. StackSym *
  1007. RegOpnd::GetStackSymInternal() const
  1008. {
  1009. return this->m_sym;
  1010. }
  1011. StackSym *
  1012. RegOpnd::TryGetStackSym(Opnd *const opnd)
  1013. {
  1014. return opnd && opnd->IsRegOpnd() ? opnd->AsRegOpnd()->m_sym : nullptr;
  1015. }
  1016. ///----------------------------------------------------------------------------
  1017. ///
  1018. /// RegOpnd::IsEqual
  1019. ///
  1020. ///----------------------------------------------------------------------------
  1021. bool
  1022. RegOpnd::IsEqualInternal(Opnd *opnd)
  1023. {
  1024. Assert(m_kind == OpndKindReg);
  1025. return IsSameRegUntyped(opnd) && (this->GetType() == opnd->GetType());
  1026. }
  1027. void
  1028. RegOpnd::FreeInternal(Func *func)
  1029. {
  1030. Assert(m_kind == OpndKindReg);
  1031. JitAdelete(func->m_alloc, this);
  1032. }
  1033. ///----------------------------------------------------------------------------
  1034. ///
  1035. /// RegOpnd::IsSameReg
  1036. ///
  1037. /// Same as IsEqual except the type only need to be equal size
  1038. ///
  1039. ///----------------------------------------------------------------------------
  1040. bool
  1041. RegOpnd::IsSameReg(Opnd *opnd)
  1042. {
  1043. return IsSameRegUntyped(opnd) && (TySize[this->GetType()] == TySize[opnd->GetType()]);
  1044. }
  1045. ///----------------------------------------------------------------------------
  1046. ///
  1047. /// RegOpnd::IsSameRegUntyped
  1048. ///
  1049. /// Same as IsEqual but without any types comparison
  1050. ///
  1051. ///----------------------------------------------------------------------------
  1052. bool
  1053. RegOpnd::IsSameRegUntyped(Opnd *opnd)
  1054. {
  1055. if (!opnd->IsRegOpnd())
  1056. {
  1057. return false;
  1058. }
  1059. RegOpnd *regOpnd = opnd->AsRegOpnd();
  1060. if (m_reg != RegNOREG)
  1061. {
  1062. return m_reg == regOpnd->m_reg;
  1063. }
  1064. return m_sym == regOpnd->m_sym && regOpnd->m_reg == RegNOREG;
  1065. }
  1066. ///----------------------------------------------------------------------------
  1067. ///
  1068. /// ArrayRegOpnd
  1069. ///
  1070. ///----------------------------------------------------------------------------
  1071. ArrayRegOpnd::ArrayRegOpnd(
  1072. StackSym *const arraySym,
  1073. const ValueType valueType,
  1074. StackSym *const headSegmentSym,
  1075. StackSym *const headSegmentLengthSym,
  1076. StackSym *const lengthSym,
  1077. const bool eliminatedLowerBoundCheck,
  1078. const bool eliminatedUpperBoundCheck)
  1079. : RegOpnd(arraySym, RegNOREG, TyVar),
  1080. headSegmentSym(headSegmentSym),
  1081. headSegmentLengthSym(headSegmentLengthSym),
  1082. lengthSym(lengthSym),
  1083. eliminatedLowerBoundCheck(eliminatedLowerBoundCheck),
  1084. eliminatedUpperBoundCheck(eliminatedUpperBoundCheck)
  1085. {
  1086. Assert(valueType.IsAnyOptimizedArray());
  1087. m_valueType = valueType;
  1088. m_isArrayRegOpnd = true;
  1089. }
  1090. ArrayRegOpnd::ArrayRegOpnd(
  1091. const RegOpnd &other,
  1092. StackSym *const arraySym,
  1093. const ValueType valueType,
  1094. StackSym *const headSegmentSym,
  1095. StackSym *const headSegmentLengthSym,
  1096. StackSym *const lengthSym,
  1097. const bool eliminatedLowerBoundCheck,
  1098. const bool eliminatedUpperBoundCheck)
  1099. : RegOpnd(other, arraySym),
  1100. headSegmentSym(headSegmentSym),
  1101. headSegmentLengthSym(headSegmentLengthSym),
  1102. lengthSym(lengthSym),
  1103. eliminatedLowerBoundCheck(eliminatedLowerBoundCheck),
  1104. eliminatedUpperBoundCheck(eliminatedUpperBoundCheck)
  1105. {
  1106. Assert(valueType.IsAnyOptimizedArray());
  1107. m_valueType = valueType;
  1108. m_isArrayRegOpnd = true;
  1109. }
  1110. ArrayRegOpnd *ArrayRegOpnd::New(
  1111. StackSym *const arraySym,
  1112. const ValueType valueType,
  1113. StackSym *const headSegmentSym,
  1114. StackSym *const headSegmentLengthSym,
  1115. StackSym *const lengthSym,
  1116. const bool eliminatedLowerBoundCheck,
  1117. const bool eliminatedUpperBoundCheck,
  1118. Func *const func)
  1119. {
  1120. Assert(func);
  1121. return
  1122. JitAnew(
  1123. func->m_alloc,
  1124. ArrayRegOpnd,
  1125. arraySym,
  1126. valueType,
  1127. headSegmentSym,
  1128. headSegmentLengthSym,
  1129. lengthSym,
  1130. eliminatedLowerBoundCheck,
  1131. eliminatedUpperBoundCheck);
  1132. }
  1133. ArrayRegOpnd *ArrayRegOpnd::New(
  1134. const RegOpnd *const other,
  1135. const ValueType valueType,
  1136. StackSym *const headSegmentSym,
  1137. StackSym *const headSegmentLengthSym,
  1138. StackSym *const lengthSym,
  1139. const bool eliminatedLowerBoundCheck,
  1140. const bool eliminatedUpperBoundCheck,
  1141. Func *const func)
  1142. {
  1143. Assert(func);
  1144. return
  1145. JitAnew(
  1146. func->m_alloc,
  1147. ArrayRegOpnd,
  1148. *other,
  1149. other->m_sym,
  1150. valueType,
  1151. headSegmentSym,
  1152. headSegmentLengthSym,
  1153. lengthSym,
  1154. eliminatedLowerBoundCheck,
  1155. eliminatedUpperBoundCheck);
  1156. }
  1157. RegOpnd *ArrayRegOpnd::CopyAsRegOpnd(Func *func)
  1158. {
  1159. RegOpnd *const regOpndCopy = RegOpnd::CopyInternal(func);
  1160. Assert(!regOpndCopy->IsArrayRegOpnd());
  1161. return regOpndCopy;
  1162. }
  1163. ArrayRegOpnd *ArrayRegOpnd::CopyInternalSub(Func *func)
  1164. {
  1165. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1166. return Clone(m_sym, headSegmentSym, headSegmentLengthSym, lengthSym, func);
  1167. }
  1168. ArrayRegOpnd *ArrayRegOpnd::CloneDefInternalSub(Func *func)
  1169. {
  1170. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1171. return
  1172. Clone(
  1173. m_sym ? m_sym->CloneDef(func) : nullptr,
  1174. headSegmentSym ? headSegmentSym->CloneUse(func) : nullptr,
  1175. headSegmentLengthSym ? headSegmentLengthSym->CloneUse(func) : nullptr,
  1176. lengthSym ? lengthSym->CloneUse(func) : nullptr,
  1177. func);
  1178. }
  1179. ArrayRegOpnd *ArrayRegOpnd::CloneUseInternalSub(Func *func)
  1180. {
  1181. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1182. return
  1183. Clone(
  1184. m_sym ? m_sym->CloneUse(func) : nullptr,
  1185. headSegmentSym ? headSegmentSym->CloneUse(func) : nullptr,
  1186. headSegmentLengthSym ? headSegmentLengthSym->CloneUse(func) : nullptr,
  1187. lengthSym ? lengthSym->CloneUse(func) : nullptr,
  1188. func);
  1189. }
  1190. ArrayRegOpnd *ArrayRegOpnd::Clone(
  1191. StackSym *const arraySym,
  1192. StackSym *const headSegmentSym,
  1193. StackSym *const headSegmentLengthSym,
  1194. StackSym *const lengthSym,
  1195. Func *const func) const
  1196. {
  1197. Assert(func);
  1198. // Careful how clones are used. Only GlobOpt knows when it's valid to use the information in this class, so ideally cloning
  1199. // should be done only at lowering time.
  1200. return
  1201. JitAnew(
  1202. func->m_alloc,
  1203. ArrayRegOpnd,
  1204. *this,
  1205. arraySym,
  1206. m_valueType,
  1207. headSegmentSym,
  1208. headSegmentLengthSym,
  1209. lengthSym,
  1210. eliminatedLowerBoundCheck,
  1211. eliminatedUpperBoundCheck);
  1212. }
  1213. void ArrayRegOpnd::FreeInternalSub(Func *func)
  1214. {
  1215. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1216. JitAdelete(func->m_alloc, this);
  1217. }
  1218. ///----------------------------------------------------------------------------
  1219. ///
  1220. /// IntConstOpnd::New
  1221. ///
  1222. /// Creates a new IntConstOpnd.
  1223. ///
  1224. ///----------------------------------------------------------------------------
  1225. IntConstOpnd *
  1226. IntConstOpnd::New(IntConstType value, IRType type, Func *func, bool dontEncode)
  1227. {
  1228. IntConstOpnd * intConstOpnd;
  1229. Assert(TySize[type] <= sizeof(IntConstType));
  1230. intConstOpnd = JitAnew(func->m_alloc, IR::IntConstOpnd);
  1231. intConstOpnd->m_type = type;
  1232. intConstOpnd->m_kind = OpndKindIntConst;
  1233. intConstOpnd->m_dontEncode = dontEncode;
  1234. intConstOpnd->SetValue(value);
  1235. return intConstOpnd;
  1236. }
  1237. ///----------------------------------------------------------------------------
  1238. ///
  1239. /// IntConstOpnd::CreateIntConstOpndFromType
  1240. ///
  1241. /// Create an IntConstOpnd or Int64ConstOpnd depending on the IRType.
  1242. ///
  1243. ///----------------------------------------------------------------------------
  1244. IR::Opnd* IntConstOpnd::NewFromType(int64 value, IRType type, Func* func)
  1245. {
  1246. if (IRType_IsInt64(type))
  1247. {
  1248. return Int64ConstOpnd::New(value, type, func);
  1249. }
  1250. Assert(value < (int64)UINT_MAX);
  1251. return IntConstOpnd::New((IntConstType)value, type, func);
  1252. }
  1253. ///----------------------------------------------------------------------------
  1254. ///
  1255. /// IntConstOpnd::Copy
  1256. ///
  1257. /// Returns a copy of this opnd.
  1258. ///
  1259. ///----------------------------------------------------------------------------
  1260. IntConstOpnd *
  1261. IntConstOpnd::CopyInternal(Func *func)
  1262. {
  1263. Assert(m_kind == OpndKindIntConst);
  1264. IntConstOpnd * newOpnd;
  1265. newOpnd = IntConstOpnd::New(m_value, m_type, func, m_dontEncode);
  1266. newOpnd->m_valueType = m_valueType;
  1267. return newOpnd;
  1268. }
  1269. ///----------------------------------------------------------------------------
  1270. ///
  1271. /// IntConstOpnd::IsEqual
  1272. ///
  1273. ///----------------------------------------------------------------------------
  1274. bool
  1275. IntConstOpnd::IsEqualInternal(Opnd *opnd)
  1276. {
  1277. Assert(m_kind == OpndKindIntConst);
  1278. if (!opnd->IsIntConstOpnd() || this->GetType() != opnd->GetType())
  1279. {
  1280. return false;
  1281. }
  1282. return m_value == opnd->AsIntConstOpnd()->m_value;
  1283. }
  1284. void
  1285. IntConstOpnd::FreeInternal(Func *func)
  1286. {
  1287. Assert(m_kind == OpndKindIntConst);
  1288. JitAdelete(func->m_alloc, this);
  1289. }
  1290. ///----------------------------------------------------------------------------
  1291. ///
  1292. /// IntConstOpnd::SetValue
  1293. ///
  1294. /// Modifies the value of the IntConstOpnd
  1295. ///
  1296. ///----------------------------------------------------------------------------
  1297. void
  1298. IntConstOpnd::SetValue(IntConstType value)
  1299. {
  1300. if (sizeof(IntConstType) > sizeof(int32))
  1301. {
  1302. Assert(m_type != TyInt32 || (value >= INT32_MIN && value <= INT32_MAX));
  1303. Assert(m_type != TyUint32 || (value >= 0 && value <= UINT32_MAX));
  1304. }
  1305. // TODO: These should be uncommented, unfortunately, Lowerer::UseWithNewType
  1306. // can change m_type (by calling SetType) in such a way that it violates these constraints.
  1307. // If CopyInternal is later called on the IntConstOpnd, these will fail.
  1308. // Assert(m_type != TyInt16 || (value >= INT16_MIN && value <= INT16_MAX));
  1309. // Assert(m_type != TyUint16 || (value >= 0 && value <= UINT16_MAX));
  1310. // Assert(m_type != TyInt8 || (value >= INT8_MIN && value <= INT8_MAX));
  1311. // Assert(m_type != TyUint8 || (value >= 0 && value <= UINT8_MAX));
  1312. m_value = value;
  1313. }
  1314. ///----------------------------------------------------------------------------
  1315. ///
  1316. /// IntConstOpnd::AsInt32
  1317. ///
  1318. /// Retrieves the value of the int const opnd as a signed 32-bit integer.
  1319. ///
  1320. ///----------------------------------------------------------------------------
  1321. int32
  1322. IntConstOpnd::AsInt32()
  1323. {
  1324. // TODO: Currently, there are cases where we construct IntConstOpnd with TyInt32
  1325. // and retrieve value out as uint32 (or vice versa). Because of these, we allow
  1326. // AsInt32/AsUint32 to cast between int32/uint32 in a lossy manner for now.
  1327. // In the future, we should tighten up usage of IntConstOpnd to avoid these casts
  1328. if (sizeof(IntConstType) == sizeof(int32))
  1329. {
  1330. return (int32)m_value;
  1331. }
  1332. if (m_type == TyUint32)
  1333. {
  1334. Assert(m_value >= 0 && m_value <= UINT32_MAX);
  1335. return (int32)(uint32)m_value;
  1336. }
  1337. Assert(Math::FitsInDWord(m_value));
  1338. return (int32)m_value;
  1339. }
  1340. ///----------------------------------------------------------------------------
  1341. ///
  1342. /// IntConstOpnd::AsUint32
  1343. ///
  1344. /// Retrieves the value of the int const opnd as an unsigned 32-bit integer.
  1345. ///
  1346. ///----------------------------------------------------------------------------
  1347. uint32
  1348. IntConstOpnd::AsUint32()
  1349. {
  1350. // TODO: See comment in AsInt32() regarding casts from int32 to uint32
  1351. if (sizeof(uint32) == sizeof(IntConstType))
  1352. {
  1353. return (uint32)m_value;
  1354. }
  1355. Assert(sizeof(uint32) < sizeof(IntConstType));
  1356. Assert(m_value >= 0 && m_value <= UINT32_MAX);
  1357. return (uint32)m_value;
  1358. }
  1359. ///----------------------------------------------------------------------------
  1360. ///
  1361. /// Int64ConstOpnd Methods
  1362. ///
  1363. ///----------------------------------------------------------------------------
  1364. IR::Int64ConstOpnd* Int64ConstOpnd::New(int64 value, IRType type, Func *func)
  1365. {
  1366. AssertMsg(func->GetJITFunctionBody()->IsWasmFunction(), "Only WebAssembly functions should have int64 const operands. Use IntConstOpnd for size_t type");
  1367. Int64ConstOpnd * intConstOpnd;
  1368. Assert(TySize[type] == sizeof(int64));
  1369. intConstOpnd = JitAnew(func->m_alloc, IR::Int64ConstOpnd);
  1370. intConstOpnd->m_type = type;
  1371. intConstOpnd->m_kind = OpndKindInt64Const;
  1372. intConstOpnd->m_value = value;
  1373. return intConstOpnd;
  1374. }
  1375. IR::Int64ConstOpnd* Int64ConstOpnd::CopyInternal(Func *func)
  1376. {
  1377. Assert(m_kind == OpndKindInt64Const);
  1378. Int64ConstOpnd * newOpnd;
  1379. newOpnd = Int64ConstOpnd::New(m_value, m_type, func);
  1380. newOpnd->m_valueType = m_valueType;
  1381. return newOpnd;
  1382. }
  1383. bool Int64ConstOpnd::IsEqualInternal(Opnd *opnd)
  1384. {
  1385. Assert(m_kind == OpndKindInt64Const);
  1386. if (!opnd->IsInt64ConstOpnd() || this->GetType() != opnd->GetType())
  1387. {
  1388. return false;
  1389. }
  1390. return m_value == opnd->AsInt64ConstOpnd()->m_value;
  1391. }
  1392. void Int64ConstOpnd::FreeInternal(Func * func)
  1393. {
  1394. Assert(m_kind == OpndKindInt64Const);
  1395. JitAdelete(func->m_alloc, this);
  1396. }
  1397. ///----------------------------------------------------------------------------
  1398. ///
  1399. /// RegBVOpnd::New
  1400. ///
  1401. /// Creates a new IntConstOpnd.
  1402. ///
  1403. ///----------------------------------------------------------------------------
  1404. RegBVOpnd *
  1405. RegBVOpnd::New(BVUnit value, IRType type, Func *func)
  1406. {
  1407. RegBVOpnd * regBVOpnd;
  1408. regBVOpnd = JitAnew(func->m_alloc, IR::RegBVOpnd);
  1409. regBVOpnd->m_value.Copy(value);
  1410. regBVOpnd->m_type = type;
  1411. regBVOpnd->m_kind = OpndKindRegBV;
  1412. return regBVOpnd;
  1413. }
  1414. ///----------------------------------------------------------------------------
  1415. ///
  1416. /// RegBVOpnd::Copy
  1417. ///
  1418. /// Returns a copy of this opnd.
  1419. ///
  1420. ///----------------------------------------------------------------------------
  1421. RegBVOpnd *
  1422. RegBVOpnd::CopyInternal(Func *func)
  1423. {
  1424. Assert(m_kind == OpndKindRegBV);
  1425. RegBVOpnd * newOpnd;
  1426. newOpnd = RegBVOpnd::New(m_value, m_type, func);
  1427. newOpnd->m_valueType = m_valueType;
  1428. return newOpnd;
  1429. }
  1430. ///----------------------------------------------------------------------------
  1431. ///
  1432. /// RegBVOpnd::IsEqual
  1433. ///
  1434. ///----------------------------------------------------------------------------
  1435. bool
  1436. RegBVOpnd::IsEqualInternal(Opnd *opnd)
  1437. {
  1438. Assert(m_kind == OpndKindRegBV);
  1439. if (!opnd->IsRegBVOpnd() || this->GetType() != opnd->GetType())
  1440. {
  1441. return false;
  1442. }
  1443. return m_value.Equal(opnd->AsRegBVOpnd()->m_value);
  1444. }
  1445. void
  1446. RegBVOpnd::FreeInternal(Func *func)
  1447. {
  1448. Assert(m_kind == OpndKindRegBV);
  1449. JitAdelete(func->m_alloc, this);
  1450. }
  1451. ///----------------------------------------------------------------------------
  1452. ///
  1453. /// FloatConstOpnd::New
  1454. ///
  1455. /// Creates a new FloatConstOpnd.
  1456. ///
  1457. ///----------------------------------------------------------------------------
  1458. FloatConstOpnd *
  1459. FloatConstOpnd::New(FloatConstType value, IRType type, Func *func)
  1460. {
  1461. FloatConstOpnd * floatConstOpnd;
  1462. floatConstOpnd = JitAnew(func->m_alloc, IR::FloatConstOpnd);
  1463. floatConstOpnd->m_value = value;
  1464. floatConstOpnd->m_type = type;
  1465. #if !FLOATVAR
  1466. floatConstOpnd->m_number = nullptr;
  1467. #endif
  1468. floatConstOpnd->m_kind = OpndKindFloatConst;
  1469. return floatConstOpnd;
  1470. }
  1471. FloatConstOpnd *
  1472. FloatConstOpnd::New(Js::Var floatVar, IRType type, Func *func, Js::Var varLocal /*= nullptr*/)
  1473. {
  1474. Assert((varLocal && Js::JavascriptNumber::Is(varLocal)) || Js::JavascriptNumber::Is(floatVar));
  1475. FloatConstType value = Js::JavascriptNumber::GetValue(varLocal ? varLocal : floatVar);
  1476. FloatConstOpnd * floatConstOpnd = FloatConstOpnd::New(value, type, func);
  1477. #if !FLOATVAR
  1478. floatConstOpnd->m_number = floatVar;
  1479. floatConstOpnd->m_numberCopy = (Js::JavascriptNumber*)varLocal;
  1480. #endif
  1481. return floatConstOpnd;
  1482. }
  1483. AddrOpnd *
  1484. FloatConstOpnd::GetAddrOpnd(Func *func, bool dontEncode)
  1485. {
  1486. #if !FLOATVAR
  1487. if (this->m_number)
  1488. {
  1489. return AddrOpnd::New(this->m_number, (Js::TaggedNumber::Is(this->m_number) ? AddrOpndKindConstantVar : AddrOpndKindDynamicVar), func, dontEncode, this->m_numberCopy);
  1490. }
  1491. #endif
  1492. IR::AddrOpnd *opnd = AddrOpnd::NewFromNumber(this->m_value, func, dontEncode);
  1493. #if !FLOATVAR
  1494. this->m_number = opnd->m_address;
  1495. #endif
  1496. return opnd;
  1497. }
  1498. ///----------------------------------------------------------------------------
  1499. ///
  1500. /// FloatConstOpnd::Copy
  1501. ///
  1502. /// Returns a copy of this opnd.
  1503. ///
  1504. ///----------------------------------------------------------------------------
  1505. FloatConstOpnd *
  1506. FloatConstOpnd::CopyInternal(Func *func)
  1507. {
  1508. Assert(m_kind == OpndKindFloatConst);
  1509. FloatConstOpnd * newOpnd;
  1510. newOpnd = FloatConstOpnd::New(m_value, m_type, func);
  1511. newOpnd->m_valueType = m_valueType;
  1512. return newOpnd;
  1513. }
  1514. ///----------------------------------------------------------------------------
  1515. ///
  1516. /// FloatConstOpnd::IsEqual
  1517. ///
  1518. ///----------------------------------------------------------------------------
  1519. bool
  1520. FloatConstOpnd::IsEqualInternal(Opnd *opnd)
  1521. {
  1522. Assert(m_kind == OpndKindFloatConst);
  1523. if (!opnd->IsFloatConstOpnd() || this->GetType() != opnd->GetType())
  1524. {
  1525. return false;
  1526. }
  1527. return m_value == opnd->AsFloatConstOpnd()->m_value;
  1528. }
  1529. void
  1530. FloatConstOpnd::FreeInternal(Func *func)
  1531. {
  1532. Assert(m_kind == OpndKindFloatConst);
  1533. JitAdelete(func->m_alloc, this);
  1534. }
  1535. ///----------------------------------------------------------------------------
  1536. ///
  1537. /// Float32ConstOpnd::New
  1538. ///
  1539. /// Creates a new Float32ConstOpnd.
  1540. ///
  1541. ///----------------------------------------------------------------------------
  1542. Float32ConstOpnd *
  1543. Float32ConstOpnd::New(float value, IRType type, Func *func)
  1544. {
  1545. Assert(type == IRType::TyFloat32); //TODO: should we even allow specifying a type here? It should always be TyFloat32
  1546. Float32ConstOpnd * Float32ConstOpnd;
  1547. Float32ConstOpnd = JitAnew(func->m_alloc, IR::Float32ConstOpnd);
  1548. Float32ConstOpnd->m_value = value;
  1549. Float32ConstOpnd->m_type = type;
  1550. Float32ConstOpnd->m_kind = OpndKindFloat32Const;
  1551. return Float32ConstOpnd;
  1552. }
  1553. ///----------------------------------------------------------------------------
  1554. ///
  1555. /// Float32ConstOpnd::Copy
  1556. ///
  1557. /// Returns a copy of this opnd.
  1558. ///
  1559. ///----------------------------------------------------------------------------
  1560. Float32ConstOpnd *
  1561. Float32ConstOpnd::CopyInternal(Func *func)
  1562. {
  1563. Assert(m_kind == OpndKindFloat32Const);
  1564. Float32ConstOpnd * newOpnd;
  1565. newOpnd = Float32ConstOpnd::New(m_value, m_type, func);
  1566. newOpnd->m_valueType = m_valueType;
  1567. return newOpnd;
  1568. }
  1569. ///----------------------------------------------------------------------------
  1570. ///
  1571. /// Float32ConstOpnd::IsEqual
  1572. ///
  1573. ///----------------------------------------------------------------------------
  1574. bool
  1575. Float32ConstOpnd::IsEqualInternal(Opnd *opnd)
  1576. {
  1577. Assert(m_kind == OpndKindFloat32Const);
  1578. if (!opnd->IsFloat32ConstOpnd() || this->GetType() != opnd->GetType() /* TODO: could this be turned into an assert*/)
  1579. {
  1580. return false;
  1581. }
  1582. return m_value == opnd->AsFloat32ConstOpnd()->m_value;
  1583. }
  1584. void
  1585. Float32ConstOpnd::FreeInternal(Func *func)
  1586. {
  1587. Assert(m_kind == OpndKindFloat32Const);
  1588. JitAdelete(func->m_alloc, this);
  1589. }
  1590. ///----------------------------------------------------------------------------
  1591. ///
  1592. /// Simd128ConstOpnd::New
  1593. ///
  1594. /// Creates a new FloatConstOpnd.
  1595. ///
  1596. ///----------------------------------------------------------------------------
  1597. Simd128ConstOpnd *
  1598. Simd128ConstOpnd::New(AsmJsSIMDValue value, IRType type, Func *func)
  1599. {
  1600. Simd128ConstOpnd * simd128ConstOpnd;
  1601. simd128ConstOpnd = JitAnew(func->m_alloc, IR::Simd128ConstOpnd);
  1602. simd128ConstOpnd->m_value = value;
  1603. simd128ConstOpnd->m_type = type;
  1604. simd128ConstOpnd->m_kind = OpndKindSimd128Const;
  1605. return simd128ConstOpnd;
  1606. }
  1607. ///----------------------------------------------------------------------------
  1608. ///
  1609. /// Simd128ConstOpnd::Copy
  1610. ///
  1611. /// Returns a copy of this opnd.
  1612. ///
  1613. ///----------------------------------------------------------------------------
  1614. Simd128ConstOpnd *
  1615. Simd128ConstOpnd::CopyInternal(Func *func)
  1616. {
  1617. Assert(m_kind == OpndKindSimd128Const);
  1618. Simd128ConstOpnd * newOpnd;
  1619. newOpnd = Simd128ConstOpnd::New(m_value, m_type, func);
  1620. newOpnd->m_valueType = m_valueType;
  1621. return newOpnd;
  1622. }
  1623. ///----------------------------------------------------------------------------
  1624. ///
  1625. /// Simd128ConstOpnd::IsEqual
  1626. ///
  1627. ///----------------------------------------------------------------------------
  1628. bool
  1629. Simd128ConstOpnd::IsEqualInternal(Opnd *opnd)
  1630. {
  1631. Assert(m_kind == OpndKindSimd128Const);
  1632. if (!opnd->IsSimd128ConstOpnd() || this->GetType() != opnd->GetType())
  1633. {
  1634. return false;
  1635. }
  1636. return m_value == opnd->AsSimd128ConstOpnd()->m_value;
  1637. }
  1638. void
  1639. Simd128ConstOpnd::FreeInternal(Func *func)
  1640. {
  1641. Assert(m_kind == OpndKindSimd128Const);
  1642. JitAdelete(func->m_alloc, this);
  1643. }
  1644. ///----------------------------------------------------------------------------
  1645. ///
  1646. /// HelperCallOpnd::New
  1647. ///
  1648. /// Creates a new HelperCallOpnd.
  1649. ///
  1650. ///----------------------------------------------------------------------------
  1651. HelperCallOpnd *
  1652. HelperCallOpnd::New(JnHelperMethod fnHelper, Func *func)
  1653. {
  1654. HelperCallOpnd *helperCallOpnd = JitAnew(func->m_alloc, IR::HelperCallOpnd);
  1655. helperCallOpnd->Init(fnHelper);
  1656. return helperCallOpnd;
  1657. }
  1658. void
  1659. HelperCallOpnd::Init(JnHelperMethod fnHelper)
  1660. {
  1661. Assert(fnHelper != IR::HelperInvalid);
  1662. this->m_fnHelper = fnHelper;
  1663. this->m_type = TyMachPtr;
  1664. this->m_kind = OpndKindHelperCall;
  1665. }
  1666. ///----------------------------------------------------------------------------
  1667. ///
  1668. /// HelperCallOpnd::Copy
  1669. ///
  1670. /// Returns a copy of this opnd.
  1671. ///
  1672. ///----------------------------------------------------------------------------
  1673. HelperCallOpnd *
  1674. HelperCallOpnd::CopyInternal(Func *func)
  1675. {
  1676. Assert(m_kind == OpndKindHelperCall);
  1677. HelperCallOpnd *const newOpnd = HelperCallOpnd::New(m_fnHelper, func);
  1678. newOpnd->m_valueType = m_valueType;
  1679. return newOpnd;
  1680. }
  1681. ///----------------------------------------------------------------------------
  1682. ///
  1683. /// HelperCallOpnd::IsEqual
  1684. ///
  1685. ///----------------------------------------------------------------------------
  1686. bool
  1687. HelperCallOpnd::IsEqualInternal(Opnd *opnd)
  1688. {
  1689. Assert(m_kind == OpndKindHelperCall);
  1690. if (!opnd->IsHelperCallOpnd())
  1691. {
  1692. return false;
  1693. }
  1694. return m_fnHelper == opnd->AsHelperCallOpnd()->m_fnHelper;
  1695. }
  1696. void
  1697. HelperCallOpnd::FreeInternal(Func *func)
  1698. {
  1699. Assert(m_kind == OpndKindHelperCall);
  1700. JitAdelete(func->m_alloc, this);
  1701. }
  1702. DiagHelperCallOpnd *
  1703. DiagHelperCallOpnd::New(JnHelperMethod fnHelper, Func *func, int argCount)
  1704. {
  1705. DiagHelperCallOpnd *helperCallOpnd = JitAnew(func->m_alloc, IR::DiagHelperCallOpnd);
  1706. helperCallOpnd->Init(fnHelper);
  1707. helperCallOpnd->m_argCount = argCount;
  1708. helperCallOpnd->isDiagHelperCallOpnd = true;
  1709. return helperCallOpnd;
  1710. }
  1711. DiagHelperCallOpnd *
  1712. DiagHelperCallOpnd::CopyInternalSub(Func *func)
  1713. {
  1714. Assert(m_kind == OpndKindHelperCall && this->IsDiagHelperCallOpnd());
  1715. DiagHelperCallOpnd *const newOpnd = DiagHelperCallOpnd::New(m_fnHelper, func, m_argCount);
  1716. newOpnd->m_valueType = m_valueType;
  1717. return newOpnd;
  1718. }
  1719. bool
  1720. DiagHelperCallOpnd::IsEqualInternalSub(Opnd *opnd)
  1721. {
  1722. Assert(m_kind == OpndKindHelperCall && this->IsDiagHelperCallOpnd());
  1723. if (!opnd->IsHelperCallOpnd() || !opnd->AsHelperCallOpnd()->IsDiagHelperCallOpnd())
  1724. {
  1725. return false;
  1726. }
  1727. return
  1728. m_fnHelper == opnd->AsHelperCallOpnd()->m_fnHelper &&
  1729. m_argCount == static_cast<DiagHelperCallOpnd*>(opnd)->m_argCount;
  1730. }
  1731. ///----------------------------------------------------------------------------
  1732. ///
  1733. /// AddrOpnd::New
  1734. ///
  1735. /// Creates a new AddrOpnd.
  1736. ///
  1737. ///----------------------------------------------------------------------------
  1738. AddrOpnd *
  1739. AddrOpnd::New(intptr_t address, AddrOpndKind addrOpndKind, Func *func, bool dontEncode /* = false */, Js::Var varLocal /* = nullptr*/)
  1740. {
  1741. AddrOpnd * addrOpnd;
  1742. addrOpnd = JitAnew(func->m_alloc, IR::AddrOpnd);
  1743. // TODO (michhol): OOP JIT, use intptr_t instead of Js::Var by default so people don't try to dereference
  1744. addrOpnd->m_address = (Js::Var)address;
  1745. addrOpnd->m_localAddress = func->IsOOPJIT() ? varLocal : (Js::Var)address;
  1746. addrOpnd->addrOpndKind = addrOpndKind;
  1747. addrOpnd->m_type = addrOpnd->IsVar() ? TyVar : TyMachPtr;
  1748. addrOpnd->m_dontEncode = dontEncode;
  1749. addrOpnd->m_isFunction = false;
  1750. if (address && addrOpnd->IsVar())
  1751. {
  1752. if (Js::TaggedInt::Is(address))
  1753. {
  1754. addrOpnd->m_valueType = ValueType::GetTaggedInt();
  1755. addrOpnd->SetValueTypeFixed();
  1756. }
  1757. else if (
  1758. #if !FLOATVAR
  1759. !func->IsOOPJIT() && CONFIG_FLAG(OOPJITMissingOpts) &&
  1760. #endif
  1761. Js::JavascriptNumber::Is_NoTaggedIntCheck(addrOpnd->m_address))
  1762. {
  1763. addrOpnd->m_valueType =
  1764. Js::JavascriptNumber::IsInt32_NoChecks(addrOpnd->m_address)
  1765. ? ValueType::GetInt(false)
  1766. : ValueType::Float;
  1767. addrOpnd->SetValueTypeFixed();
  1768. }
  1769. }
  1770. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1771. addrOpnd->decodedValue = 0;
  1772. addrOpnd->wasVar = addrOpnd->IsVar();
  1773. #endif
  1774. addrOpnd->m_kind = OpndKindAddr;
  1775. return addrOpnd;
  1776. }
  1777. AddrOpnd *
  1778. AddrOpnd::New(Js::Var address, AddrOpndKind addrOpndKind, Func *func, bool dontEncode /* = false */, Js::Var varLocal /* = nullptr*/)
  1779. {
  1780. AddrOpnd * addrOpnd;
  1781. addrOpnd = JitAnew(func->m_alloc, IR::AddrOpnd);
  1782. addrOpnd->m_address = address;
  1783. addrOpnd->m_localAddress = func->IsOOPJIT() ? varLocal : address;
  1784. addrOpnd->addrOpndKind = addrOpndKind;
  1785. addrOpnd->m_type = addrOpnd->IsVar()? TyVar : TyMachPtr;
  1786. addrOpnd->m_dontEncode = dontEncode;
  1787. addrOpnd->m_isFunction = false;
  1788. addrOpnd->m_metadata = nullptr;
  1789. if(address && addrOpnd->IsVar())
  1790. {
  1791. if(Js::TaggedInt::Is(address))
  1792. {
  1793. addrOpnd->m_valueType = ValueType::GetTaggedInt();
  1794. addrOpnd->SetValueTypeFixed();
  1795. }
  1796. else
  1797. {
  1798. Js::Var var = varLocal ? varLocal : address;
  1799. if (
  1800. #if !FLOATVAR
  1801. varLocal || (!func->IsOOPJIT() && CONFIG_FLAG(OOPJITMissingOpts)) &&
  1802. #endif
  1803. Js::JavascriptNumber::Is_NoTaggedIntCheck(var))
  1804. {
  1805. addrOpnd->m_valueType =
  1806. Js::JavascriptNumber::IsInt32_NoChecks(var)
  1807. ? ValueType::GetInt(false)
  1808. : ValueType::Float;
  1809. addrOpnd->SetValueTypeFixed();
  1810. }
  1811. }
  1812. }
  1813. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1814. addrOpnd->decodedValue = 0;
  1815. addrOpnd->wasVar = addrOpnd->IsVar();
  1816. #endif
  1817. addrOpnd->m_kind = OpndKindAddr;
  1818. return addrOpnd;
  1819. }
  1820. AddrOpnd *
  1821. AddrOpnd::NewFromNumber(int32 value, Func *func, bool dontEncode /* = false */)
  1822. {
  1823. if (!Js::TaggedInt::IsOverflow(value))
  1824. {
  1825. return New(Js::TaggedInt::ToVarUnchecked(value), AddrOpndKindConstantVar, func, dontEncode);
  1826. }
  1827. else
  1828. {
  1829. return NewFromNumberVar(value, func, dontEncode);
  1830. }
  1831. }
  1832. AddrOpnd *
  1833. AddrOpnd::NewFromNumber(int64 value, Func *func, bool dontEncode /* = false */)
  1834. {
  1835. if (!Js::TaggedInt::IsOverflow(value))
  1836. {
  1837. return New(Js::TaggedInt::ToVarUnchecked((int)value), AddrOpndKindConstantVar, func, dontEncode);
  1838. }
  1839. else
  1840. {
  1841. return NewFromNumberVar((double)value, func, dontEncode);
  1842. }
  1843. }
  1844. AddrOpnd *
  1845. AddrOpnd::NewFromNumber(double value, Func *func, bool dontEncode /* = false */)
  1846. {
  1847. //
  1848. // Check if a well-known value:
  1849. // - This significantly cuts down on the below floating-point to integer conversions.
  1850. //
  1851. if (Js::JavascriptNumber::IsNegZero(value))
  1852. {
  1853. return New(func->GetScriptContextInfo()->GetNegativeZeroAddr(), AddrOpndKindDynamicVar, func, dontEncode);
  1854. }
  1855. if (value == +0.0)
  1856. {
  1857. return New(Js::TaggedInt::ToVarUnchecked(0), AddrOpndKindConstantVar, func, dontEncode);
  1858. }
  1859. if (value == 1.0)
  1860. {
  1861. return New(Js::TaggedInt::ToVarUnchecked(1), AddrOpndKindConstantVar, func, dontEncode);
  1862. }
  1863. //
  1864. // Check if number can be reduced back into a TaggedInt:
  1865. // - This avoids extra GC.
  1866. //
  1867. int nValue = (int) value;
  1868. double dblCheck = (double) nValue;
  1869. if ((dblCheck == value) && (!Js::TaggedInt::IsOverflow(nValue)))
  1870. {
  1871. return New(Js::TaggedInt::ToVarUnchecked(nValue), AddrOpndKindConstantVar, func, dontEncode);
  1872. }
  1873. return NewFromNumberVar(value, func, dontEncode);
  1874. }
  1875. AddrOpnd *
  1876. AddrOpnd::NewFromNumberVar(double value, Func *func, bool dontEncode /* = false */)
  1877. {
  1878. Js::Var var = func->AllocateNumber((double)value);
  1879. AddrOpnd* addrOpnd = New((intptr_t)var, AddrOpndKindDynamicVar, func, dontEncode);
  1880. addrOpnd->m_valueType =
  1881. Js::JavascriptNumber::IsInt32(value)
  1882. ? ValueType::GetInt(false)
  1883. : ValueType::Float;
  1884. addrOpnd->SetValueTypeFixed();
  1885. return addrOpnd;
  1886. }
  1887. AddrOpnd *
  1888. AddrOpnd::NewNull(Func *func)
  1889. {
  1890. return AddrOpnd::New((Js::Var)0, AddrOpndKindConstantAddress, func, true);
  1891. }
  1892. ///----------------------------------------------------------------------------
  1893. ///
  1894. /// AddrOpnd::Copy
  1895. ///
  1896. /// Returns a copy of this opnd.
  1897. ///
  1898. ///----------------------------------------------------------------------------
  1899. AddrOpnd *
  1900. AddrOpnd::CopyInternal(Func *func)
  1901. {
  1902. Assert(m_kind == OpndKindAddr);
  1903. AddrOpnd * newOpnd;
  1904. newOpnd = AddrOpnd::New(nullptr, addrOpndKind, func, m_dontEncode);
  1905. // Constructor evaluates address for type, but this is invalid if the address has been encoded, so we wait to set it
  1906. newOpnd->m_address = m_address;
  1907. newOpnd->m_valueType = m_valueType;
  1908. newOpnd->m_isFunction = m_isFunction;
  1909. newOpnd->m_metadata = m_metadata;
  1910. newOpnd->SetType(m_type);
  1911. if (IsValueTypeFixed())
  1912. {
  1913. newOpnd->SetValueTypeFixed();
  1914. }
  1915. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1916. newOpnd->decodedValue = this->decodedValue;
  1917. newOpnd->wasVar = this->wasVar;
  1918. #endif
  1919. return newOpnd;
  1920. }
  1921. ///----------------------------------------------------------------------------
  1922. ///
  1923. /// AddrOpnd::IsEqual
  1924. ///
  1925. ///----------------------------------------------------------------------------
  1926. bool
  1927. AddrOpnd::IsEqualInternal(Opnd *opnd)
  1928. {
  1929. Assert(m_kind == OpndKindAddr);
  1930. if (!opnd->IsAddrOpnd())
  1931. {
  1932. return false;
  1933. }
  1934. return m_address == opnd->AsAddrOpnd()->m_address;
  1935. }
  1936. void
  1937. AddrOpnd::FreeInternal(Func *func)
  1938. {
  1939. Assert(m_kind == OpndKindAddr);
  1940. JitAdelete(func->m_alloc, this);
  1941. }
  1942. void
  1943. AddrOpnd::SetEncodedValue(Js::Var address, AddrOpndKind addrOpndKind)
  1944. {
  1945. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1946. this->decodedValue = this->m_address;
  1947. #endif
  1948. this->SetAddress(address, addrOpndKind);
  1949. }
  1950. void
  1951. AddrOpnd::SetAddress(Js::Var address, AddrOpndKind addrOpndKind)
  1952. {
  1953. this->m_address = address;
  1954. this->addrOpndKind = addrOpndKind;
  1955. }
  1956. ///----------------------------------------------------------------------------
  1957. ///
  1958. /// ListOpnd
  1959. ///
  1960. /// ListOpnd API
  1961. ///
  1962. ///----------------------------------------------------------------------------
  1963. ListOpnd *
  1964. ListOpnd::New(Func *func, __in_ecount(count) ListOpndType** opnds, int count)
  1965. {
  1966. return JitAnew(func->m_alloc, ListOpnd, func, opnds, count);
  1967. }
  1968. ListOpnd::~ListOpnd()
  1969. {
  1970. Func* func = this->m_func;
  1971. for (int i = 0; i < Count(); ++i)
  1972. {
  1973. Item(i)->UnUse();
  1974. Item(i)->Free(func);
  1975. }
  1976. JitAdeleteArray(func->m_alloc, count, opnds);
  1977. }
  1978. ListOpnd::ListOpnd(Func* func, __in_ecount(_count) ListOpndType** _opnds, int _count):
  1979. Opnd(), m_func(func), count(_count)
  1980. {
  1981. AssertOrFailFast(count > 0);
  1982. Assert(func->isPostLower || func->IsInPhase(Js::LowererPhase));
  1983. m_kind = OpndKindList;
  1984. m_type = TyMisc;
  1985. opnds = JitAnewArray(func->m_alloc, ListOpndType*, count);
  1986. for (int i = 0; i < count; ++i)
  1987. {
  1988. opnds[i] = _opnds[i]->Use(func)->AsRegOpnd();
  1989. }
  1990. }
  1991. void ListOpnd::FreeInternal(Func * func)
  1992. {
  1993. Assert(m_kind == OpndKindList);
  1994. JitAdelete(func->m_alloc, this);
  1995. }
  1996. bool ListOpnd::IsEqualInternal(Opnd * opnd)
  1997. {
  1998. Assert(m_kind == OpndKindList);
  1999. if (!opnd->IsListOpnd())
  2000. {
  2001. return false;
  2002. }
  2003. ListOpnd* l2 = opnd->AsListOpnd();
  2004. if (l2->Count() != Count())
  2005. {
  2006. return false;
  2007. }
  2008. for (int i = 0; i < Count(); ++i)
  2009. {
  2010. if (!Item(i)->IsEqual(l2->Item(i)))
  2011. {
  2012. return false;
  2013. }
  2014. }
  2015. return true;
  2016. }
  2017. Opnd * ListOpnd::CloneUseInternal(Func * func)
  2018. {
  2019. Assert(m_kind == OpndKindList);
  2020. int count = Count();
  2021. ListOpndType** opnds = JitAnewArray(func->m_alloc, ListOpndType*, count);
  2022. for (int i = 0; i < count; ++i)
  2023. {
  2024. ListOpndType* newOpnd = Item(i)->CloneUse(func)->AsRegOpnd();
  2025. opnds[i] = newOpnd;
  2026. }
  2027. ListOpnd* newList = ListOpnd::New(func, opnds, count);
  2028. JitAdeleteArray(func->m_alloc, count, opnds);
  2029. return newList;
  2030. }
  2031. Opnd * ListOpnd::CloneDefInternal(Func * func)
  2032. {
  2033. Assert(m_kind == OpndKindList);
  2034. int count = Count();
  2035. ListOpndType** opnds = JitAnewArray(func->m_alloc, RegOpnd*, count);
  2036. for (int i = 0; i < count; ++i)
  2037. {
  2038. ListOpndType* newOpnd = Item(i)->CloneDef(func)->AsRegOpnd();
  2039. opnds[i] = newOpnd;
  2040. }
  2041. ListOpnd* newList = ListOpnd::New(func, opnds, count);
  2042. JitAdeleteArray(func->m_alloc, count, opnds);
  2043. return newList;
  2044. }
  2045. Opnd * ListOpnd::CopyInternal(Func * func)
  2046. {
  2047. Assert(m_kind == OpndKindList);
  2048. return ListOpnd::New(func, opnds, Count());
  2049. }
  2050. ///----------------------------------------------------------------------------
  2051. ///
  2052. /// IndirOpnd::New
  2053. ///
  2054. /// Creates a new IndirOpnd.
  2055. ///
  2056. ///----------------------------------------------------------------------------
  2057. IndirOpnd *
  2058. IndirOpnd::New(RegOpnd *baseOpnd, RegOpnd *indexOpnd, IRType type, Func *func)
  2059. {
  2060. IndirOpnd * indirOpnd;
  2061. AssertMsg(baseOpnd, "An IndirOpnd needs a valid baseOpnd.");
  2062. indirOpnd = JitAnew(func->m_alloc, IndirOpnd);
  2063. indirOpnd->m_func = func;
  2064. indirOpnd->SetBaseOpnd(baseOpnd);
  2065. indirOpnd->SetIndexOpnd(indexOpnd);
  2066. indirOpnd->m_type = type;
  2067. indirOpnd->SetIsJITOptimizedReg(false);
  2068. indirOpnd->m_kind = OpndKindIndir;
  2069. return indirOpnd;
  2070. }
  2071. ///----------------------------------------------------------------------------
  2072. ///
  2073. /// IndirOpnd::New
  2074. ///
  2075. /// Creates a new IndirOpnd.
  2076. ///
  2077. ///----------------------------------------------------------------------------
  2078. IndirOpnd *
  2079. IndirOpnd::New(RegOpnd *baseOpnd, RegOpnd *indexOpnd, byte scale, IRType type, Func *func)
  2080. {
  2081. IndirOpnd * indirOpnd = IndirOpnd::New(baseOpnd, indexOpnd, type, func);
  2082. indirOpnd->m_scale = scale;
  2083. return indirOpnd;
  2084. }
  2085. ///----------------------------------------------------------------------------
  2086. ///
  2087. /// IndirOpnd::New
  2088. ///
  2089. /// Creates a new IndirOpnd.
  2090. ///
  2091. ///----------------------------------------------------------------------------
  2092. IndirOpnd *
  2093. IndirOpnd::New(RegOpnd *indexOpnd, int32 offset, byte scale, IRType type, Func *func)
  2094. {
  2095. IndirOpnd * indirOpnd;
  2096. indirOpnd = JitAnew(func->m_alloc, IndirOpnd);
  2097. indirOpnd->m_func = func;
  2098. indirOpnd->SetBaseOpnd(nullptr);
  2099. indirOpnd->SetOffset(offset, true);
  2100. indirOpnd->SetIndexOpnd(indexOpnd);
  2101. indirOpnd->m_type = type;
  2102. indirOpnd->SetIsJITOptimizedReg(false);
  2103. indirOpnd->m_kind = OpndKindIndir;
  2104. indirOpnd->m_scale = scale;
  2105. return indirOpnd;
  2106. }
  2107. ///----------------------------------------------------------------------------
  2108. ///
  2109. /// IndirOpnd::New
  2110. ///
  2111. /// Creates a new IndirOpnd.
  2112. ///
  2113. ///----------------------------------------------------------------------------
  2114. IndirOpnd *
  2115. IndirOpnd::New(RegOpnd *baseOpnd, int32 offset, IRType type, Func *func, bool dontEncode /* = false */)
  2116. {
  2117. IndirOpnd * indirOpnd;
  2118. indirOpnd = JitAnew(func->m_alloc, IndirOpnd);
  2119. indirOpnd->m_func = func;
  2120. indirOpnd->SetBaseOpnd(baseOpnd);
  2121. indirOpnd->SetOffset(offset, dontEncode);
  2122. indirOpnd->m_type = type;
  2123. indirOpnd->SetIsJITOptimizedReg(false);
  2124. indirOpnd->m_conversionAllowed = false;
  2125. indirOpnd->m_kind = OpndKindIndir;
  2126. return indirOpnd;
  2127. }
  2128. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  2129. ///----------------------------------------------------------------------------
  2130. ///
  2131. /// IndirOpnd::New
  2132. ///
  2133. /// Creates a new IndirOpnd.
  2134. ///
  2135. ///----------------------------------------------------------------------------
  2136. IndirOpnd *
  2137. IndirOpnd::New(RegOpnd *baseOpnd, int32 offset, IRType type, const char16 *desc, Func *func, bool dontEncode /* = false */)
  2138. {
  2139. IndirOpnd * indirOpnd = IndirOpnd::New(baseOpnd, offset, type, func);
  2140. indirOpnd->m_desc = desc;
  2141. indirOpnd->m_dontEncode = dontEncode;
  2142. return indirOpnd;
  2143. }
  2144. #endif
  2145. IndirOpnd::~IndirOpnd()
  2146. {
  2147. if (m_baseOpnd != nullptr)
  2148. {
  2149. m_baseOpnd->UnUse();
  2150. m_baseOpnd->Free(m_func);
  2151. }
  2152. if (m_indexOpnd != nullptr)
  2153. {
  2154. m_indexOpnd->UnUse();
  2155. m_indexOpnd->Free(m_func);
  2156. }
  2157. }
  2158. ///----------------------------------------------------------------------------
  2159. ///
  2160. /// IndirOpnd::Copy
  2161. ///
  2162. /// Returns a copy of this opnd.
  2163. ///
  2164. ///----------------------------------------------------------------------------
  2165. IndirOpnd *
  2166. IndirOpnd::CopyInternal(Func *func)
  2167. {
  2168. Assert(m_kind == OpndKindIndir);
  2169. IndirOpnd * newOpnd;
  2170. newOpnd = IndirOpnd::New(m_baseOpnd, m_indexOpnd, m_scale, m_type, func);
  2171. newOpnd->m_valueType = m_valueType;
  2172. newOpnd->canStoreTemp = this->canStoreTemp;
  2173. newOpnd->SetOffset(m_offset, m_dontEncode);
  2174. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  2175. newOpnd->m_conversionAllowed = this->m_conversionAllowed;
  2176. #if DBG_DUMP
  2177. newOpnd->m_addrKind = m_addrKind;
  2178. newOpnd->m_originalAddress = m_originalAddress;
  2179. #endif
  2180. return newOpnd;
  2181. }
  2182. IndirOpnd *
  2183. IndirOpnd::CloneDefInternal(Func *func)
  2184. {
  2185. Assert(m_kind == OpndKindIndir);
  2186. IndirOpnd * newOpnd;
  2187. // The components of an IndirOpnd are always uses, even if the IndirOpnd itself is a def.
  2188. RegOpnd * newBaseOpnd = m_baseOpnd ? m_baseOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  2189. RegOpnd * newIndexOpnd = m_indexOpnd ? m_indexOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  2190. newOpnd = IndirOpnd::New(newBaseOpnd, newIndexOpnd, m_scale, m_type, func);
  2191. newOpnd->SetOffset(m_offset, m_dontEncode);
  2192. #if DBG_DUMP
  2193. newOpnd->m_addrKind = m_addrKind;
  2194. newOpnd->m_originalAddress = m_originalAddress;
  2195. #endif
  2196. return newOpnd;
  2197. }
  2198. IndirOpnd *
  2199. IndirOpnd::CloneUseInternal(Func *func)
  2200. {
  2201. Assert(m_kind == OpndKindIndir);
  2202. IndirOpnd * newOpnd;
  2203. RegOpnd * newBaseOpnd = m_baseOpnd ? m_baseOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  2204. RegOpnd * newIndexOpnd = m_indexOpnd ? m_indexOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  2205. newOpnd = IndirOpnd::New(newBaseOpnd, newIndexOpnd, m_scale, m_type, func);
  2206. newOpnd->SetOffset(m_offset, m_dontEncode);
  2207. #if DBG_DUMP
  2208. newOpnd->m_addrKind = m_addrKind;
  2209. newOpnd->m_originalAddress = m_originalAddress;
  2210. #endif
  2211. return newOpnd;
  2212. }
  2213. bool
  2214. IndirOpnd::TryGetIntConstIndexValue(bool trySym, IntConstType *pValue, bool * pIsNotInt)
  2215. {
  2216. *pIsNotInt = false;
  2217. IR::RegOpnd * indexOpnd = this->GetIndexOpnd();
  2218. if (!indexOpnd)
  2219. {
  2220. *pValue = (IntConstType)this->GetOffset();
  2221. return true;
  2222. }
  2223. if (!trySym)
  2224. {
  2225. return false;
  2226. }
  2227. StackSym * indexSym = indexOpnd->m_sym;
  2228. *pIsNotInt = indexOpnd->IsNotInt();
  2229. // Const flags for type-specialized syms are not accurate during the forward pass, so the forward pass cannot use that info
  2230. // while the lowerer can. Additionally, due to value transfers being conservative in a loop prepass, the const flags can
  2231. // show that a sym has a constant value even though the value during the forward pass did not. Skip checking const flags for
  2232. // type-specialized index syms and instead, expect that once the above issues are fixed, that the forward pass would fold a
  2233. // constant index into the indir's offset.
  2234. if (!*pIsNotInt && !indexSym->IsTypeSpec() && indexSym->IsIntConst())
  2235. {
  2236. *pValue = indexSym->GetIntConstValue();
  2237. return true;
  2238. }
  2239. return false;
  2240. }
  2241. ///----------------------------------------------------------------------------
  2242. ///
  2243. /// IndirOpnd::IsEqual
  2244. ///
  2245. ///----------------------------------------------------------------------------
  2246. bool
  2247. IndirOpnd::IsEqualInternal(Opnd *opnd)
  2248. {
  2249. Assert(m_kind == OpndKindIndir);
  2250. Assert(opnd);
  2251. if (!opnd->IsIndirOpnd() || this->GetType() != opnd->GetType())
  2252. {
  2253. return false;
  2254. }
  2255. IndirOpnd *indirOpnd = opnd->AsIndirOpnd();
  2256. return m_offset == indirOpnd->m_offset
  2257. && ((m_baseOpnd == nullptr && indirOpnd->m_baseOpnd == nullptr) || (m_baseOpnd && indirOpnd->m_baseOpnd && m_baseOpnd->IsEqual(indirOpnd->m_baseOpnd)))
  2258. && ((m_indexOpnd == nullptr && indirOpnd->m_indexOpnd == nullptr) || (m_indexOpnd && indirOpnd->m_indexOpnd && m_indexOpnd->IsEqual(indirOpnd->m_indexOpnd)));
  2259. }
  2260. void
  2261. IndirOpnd::FreeInternal(Func *func)
  2262. {
  2263. Assert(m_kind == OpndKindIndir);
  2264. JitAdelete(func->m_alloc, this);
  2265. }
  2266. ///----------------------------------------------------------------------------
  2267. ///
  2268. /// IndirOpnd::SetBaseOpnd
  2269. ///
  2270. ///----------------------------------------------------------------------------
  2271. void
  2272. IndirOpnd::SetBaseOpnd(RegOpnd *baseOpnd)
  2273. {
  2274. if (m_baseOpnd)
  2275. {
  2276. m_baseOpnd->UnUse();
  2277. }
  2278. if (baseOpnd)
  2279. {
  2280. baseOpnd = baseOpnd->Use(m_func)->AsRegOpnd();
  2281. }
  2282. m_baseOpnd = baseOpnd;
  2283. }
  2284. ///----------------------------------------------------------------------------
  2285. ///
  2286. /// IndirOpnd::UnlinkBaseOpnd
  2287. ///
  2288. ///----------------------------------------------------------------------------
  2289. RegOpnd *
  2290. IndirOpnd::UnlinkBaseOpnd()
  2291. {
  2292. RegOpnd * baseOpnd = this->m_baseOpnd;
  2293. // This will also call UnUse()...
  2294. this->SetBaseOpnd(nullptr);
  2295. return baseOpnd;
  2296. }
  2297. void
  2298. IndirOpnd::ReplaceBaseOpnd(RegOpnd *newBase)
  2299. {
  2300. RegOpnd * baseOpnd = this->m_baseOpnd;
  2301. this->UnlinkBaseOpnd();
  2302. baseOpnd->Free(this->m_func);
  2303. this->SetBaseOpnd(newBase);
  2304. }
  2305. ///----------------------------------------------------------------------------
  2306. ///
  2307. /// IndirOpnd::SetIndexOpnd
  2308. ///
  2309. ///----------------------------------------------------------------------------
  2310. void
  2311. IndirOpnd::SetIndexOpnd(RegOpnd *indexOpnd)
  2312. {
  2313. if (m_indexOpnd)
  2314. {
  2315. m_indexOpnd->UnUse();
  2316. }
  2317. if (indexOpnd)
  2318. {
  2319. indexOpnd = indexOpnd->Use(m_func)->AsRegOpnd();
  2320. }
  2321. m_indexOpnd = indexOpnd;
  2322. }
  2323. ///----------------------------------------------------------------------------
  2324. ///
  2325. /// IndirOpnd::UnlinkIndexOpnd
  2326. ///
  2327. ///----------------------------------------------------------------------------
  2328. RegOpnd *
  2329. IndirOpnd::UnlinkIndexOpnd()
  2330. {
  2331. RegOpnd * indexOpnd = this->m_indexOpnd;
  2332. // This will also call UnUse()...
  2333. this->SetIndexOpnd(nullptr);
  2334. return indexOpnd;
  2335. }
  2336. void
  2337. IndirOpnd::ReplaceIndexOpnd(RegOpnd *newIndex)
  2338. {
  2339. RegOpnd * indexOpnd = this->m_indexOpnd;
  2340. this->UnlinkIndexOpnd();
  2341. indexOpnd->Free(this->m_func);
  2342. this->SetIndexOpnd(newIndex);
  2343. }
  2344. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  2345. const char16 *
  2346. IndirOpnd::GetDescription()
  2347. {
  2348. return this->m_desc;
  2349. }
  2350. bool
  2351. IndirOpnd::HasAddrKind() const
  2352. {
  2353. #if DBG_DUMP
  2354. return m_addrKind != (IR::AddrOpndKind) - 1;
  2355. #else
  2356. return false;
  2357. #endif
  2358. }
  2359. IR::AddrOpndKind
  2360. IndirOpnd::GetAddrKind() const
  2361. {
  2362. Assert(HasAddrKind());
  2363. #if DBG_DUMP
  2364. return m_addrKind;
  2365. #else
  2366. return IR::AddrOpndKindDynamicMisc;
  2367. #endif
  2368. }
  2369. void *
  2370. IndirOpnd::GetOriginalAddress() const
  2371. {
  2372. Assert(HasAddrKind());
  2373. #if DBG_DUMP
  2374. Assert(m_originalAddress != nullptr);
  2375. return m_originalAddress;
  2376. #else
  2377. return nullptr;
  2378. #endif
  2379. }
  2380. #endif
  2381. #if DBG_DUMP
  2382. void
  2383. IndirOpnd::SetAddrKind(IR::AddrOpndKind kind, void * originalAddress)
  2384. {
  2385. Assert(originalAddress != nullptr);
  2386. this->m_addrKind = kind;
  2387. this->m_originalAddress = originalAddress;
  2388. }
  2389. #endif
  2390. ///----------------------------------------------------------------------------
  2391. ///
  2392. /// MemRefOpnd::New
  2393. ///
  2394. /// Creates a new MemRefOpnd.
  2395. ///
  2396. ///----------------------------------------------------------------------------
  2397. MemRefOpnd *
  2398. MemRefOpnd::New(intptr_t pMemLoc, IRType type, Func *func, AddrOpndKind addrOpndKind)
  2399. {
  2400. MemRefOpnd * memRefOpnd = JitAnew(func->m_alloc, IR::MemRefOpnd);
  2401. memRefOpnd->m_memLoc = pMemLoc;
  2402. memRefOpnd->m_type = type;
  2403. memRefOpnd->m_kind = OpndKindMemRef;
  2404. #if DBG_DUMP
  2405. memRefOpnd->m_addrKind = addrOpndKind;
  2406. #endif
  2407. return memRefOpnd;
  2408. }
  2409. // TODO: michhol OOP JIT, remove this signature
  2410. MemRefOpnd *
  2411. MemRefOpnd::New(void * pMemLoc, IRType type, Func *func, AddrOpndKind addrOpndKind)
  2412. {
  2413. MemRefOpnd * memRefOpnd = JitAnew(func->m_alloc, IR::MemRefOpnd);
  2414. memRefOpnd->m_memLoc = (intptr_t)pMemLoc;
  2415. memRefOpnd->m_type = type;
  2416. memRefOpnd->m_kind = OpndKindMemRef;
  2417. #if DBG_DUMP
  2418. memRefOpnd->m_addrKind = addrOpndKind;
  2419. #endif
  2420. return memRefOpnd;
  2421. }
  2422. IR::AddrOpndKind
  2423. MemRefOpnd::GetAddrKind() const
  2424. {
  2425. #if DBG_DUMP
  2426. return this->m_addrKind;
  2427. #else
  2428. return AddrOpndKindDynamicMisc;
  2429. #endif
  2430. }
  2431. ///----------------------------------------------------------------------------
  2432. ///
  2433. /// MemRefOpnd::Copy
  2434. ///
  2435. /// Returns a copy of this opnd.
  2436. ///
  2437. ///----------------------------------------------------------------------------
  2438. MemRefOpnd *
  2439. MemRefOpnd::CopyInternal(Func *func)
  2440. {
  2441. Assert(m_kind == OpndKindMemRef);
  2442. MemRefOpnd * newOpnd;
  2443. newOpnd = MemRefOpnd::New(m_memLoc, m_type, func);
  2444. newOpnd->m_valueType = m_valueType;
  2445. newOpnd->m_memLoc = m_memLoc;
  2446. #if DBG_DUMP
  2447. newOpnd->m_addrKind = m_addrKind;
  2448. #endif
  2449. return newOpnd;
  2450. }
  2451. ///----------------------------------------------------------------------------
  2452. ///
  2453. /// MemRefOpnd::IsEqual
  2454. ///
  2455. ///----------------------------------------------------------------------------
  2456. bool
  2457. MemRefOpnd::IsEqualInternal(Opnd *opnd)
  2458. {
  2459. Assert(m_kind == OpndKindMemRef);
  2460. if (!opnd->IsMemRefOpnd() || this->GetType() != opnd->GetType())
  2461. {
  2462. return false;
  2463. }
  2464. MemRefOpnd *memRefOpnd = opnd->AsMemRefOpnd();
  2465. return m_memLoc == memRefOpnd->m_memLoc;
  2466. }
  2467. void
  2468. MemRefOpnd::FreeInternal(Func *func)
  2469. {
  2470. Assert(m_kind == OpndKindMemRef);
  2471. JitAdelete(func->m_alloc, this);
  2472. }
  2473. LabelOpnd *
  2474. LabelOpnd::New(LabelInstr * labelInstr, Func * func)
  2475. {
  2476. LabelOpnd * labelOpnd = JitAnew(func->m_alloc, IR::LabelOpnd);
  2477. labelOpnd->m_label = labelInstr;
  2478. labelOpnd->m_type = TyMachPtr;
  2479. labelInstr->m_hasNonBranchRef = true;
  2480. labelOpnd->m_kind = OpndKindLabel;
  2481. return labelOpnd;
  2482. }
  2483. LabelOpnd *
  2484. LabelOpnd::CopyInternal(Func * func)
  2485. {
  2486. Assert(m_kind == OpndKindLabel);
  2487. LabelOpnd * newOpnd;
  2488. newOpnd = LabelOpnd::New(m_label, func);
  2489. newOpnd->m_valueType = m_valueType;
  2490. return newOpnd;
  2491. }
  2492. bool
  2493. LabelOpnd::IsEqualInternal(Opnd * opnd)
  2494. {
  2495. Assert(m_kind == OpndKindLabel);
  2496. if (!opnd->IsLabelOpnd())
  2497. {
  2498. return false;
  2499. }
  2500. LabelOpnd * newOpnd = opnd->AsLabelOpnd();
  2501. return m_label == newOpnd->GetLabel();
  2502. }
  2503. void
  2504. LabelOpnd::FreeInternal(Func *func)
  2505. {
  2506. Assert(m_kind == OpndKindLabel);
  2507. JitAdelete(func->m_alloc, this);
  2508. }
  2509. IR::RegOpnd *
  2510. Opnd::FindRegUse(IR::RegOpnd *regOpnd)
  2511. {
  2512. StackSym *regSym = regOpnd->m_sym;
  2513. if (this->IsRegOpnd())
  2514. {
  2515. if (this->AsRegOpnd()->m_sym == regSym)
  2516. {
  2517. return this->AsRegOpnd();
  2518. }
  2519. }
  2520. else if (this->IsIndirOpnd())
  2521. {
  2522. IndirOpnd *indirOpnd = this->AsIndirOpnd();
  2523. if (indirOpnd->GetBaseOpnd() && indirOpnd->GetBaseOpnd()->m_sym == regSym)
  2524. {
  2525. return indirOpnd->GetBaseOpnd();
  2526. }
  2527. if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == regSym)
  2528. {
  2529. return indirOpnd->GetIndexOpnd();
  2530. }
  2531. }
  2532. return nullptr;
  2533. }
  2534. bool
  2535. Opnd::IsArgumentsObject()
  2536. {
  2537. // returns "false" if the sym is not single def (happens when the parent function has formals); the opnd can still be the arguments object.
  2538. // Since we need this information in the inliner where we don't track arguments object sym, going with single def is the best option.
  2539. StackSym * sym = this->GetStackSym();
  2540. return sym && sym->IsSingleDef() && sym->GetInstrDef()->HasAnyLoadHeapArgsOpCode();
  2541. }
  2542. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  2543. void
  2544. Opnd::DumpAddress(void *address, bool printToConsole, bool skipMaskedAddress)
  2545. {
  2546. if (!printToConsole)
  2547. {
  2548. return;
  2549. }
  2550. if (!Js::Configuration::Global.flags.DumpIRAddresses)
  2551. {
  2552. if (skipMaskedAddress)
  2553. {
  2554. return;
  2555. }
  2556. Output::Print(_u("0xXXXXXXXX"));
  2557. }
  2558. else
  2559. {
  2560. #ifdef TARGET_64
  2561. Output::Print(_u("0x%012I64X"), address);
  2562. #else
  2563. Output::Print(_u("0x%08X"), address);
  2564. #endif
  2565. }
  2566. }
  2567. void
  2568. Opnd::DumpFunctionInfo(_Outptr_result_buffer_(*count) char16 ** buffer, size_t * count, Js::FunctionInfo * info, bool printToConsole, _In_opt_z_ char16 const * type)
  2569. {
  2570. char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  2571. if (info->HasBody())
  2572. {
  2573. if (type == nullptr)
  2574. {
  2575. type = _u("FunctionBody");
  2576. }
  2577. Js::FunctionProxy * proxy = info->GetFunctionProxy();
  2578. WriteToBuffer(buffer, count, _u(" (%s [%s%s])"), type, proxy->GetDisplayName(), proxy->GetDebugNumberSet(debugStringBuffer));
  2579. }
  2580. else
  2581. {
  2582. if (type == nullptr)
  2583. {
  2584. type = _u("FunctionInfo");
  2585. }
  2586. WriteToBuffer(buffer, count, _u(" (%s)"), type);
  2587. }
  2588. }
  2589. template<>
  2590. void EncodableOpnd<int32>::DumpEncodable() const
  2591. {
  2592. if (name != nullptr)
  2593. {
  2594. Output::Print(_u("<%s> (value: 0x%X)"), name, m_value);
  2595. }
  2596. else if (decodedValue != 0)
  2597. {
  2598. Output::Print(_u("%d (0x%X) [encoded: 0x%X]"), decodedValue, decodedValue, m_value);
  2599. }
  2600. else
  2601. {
  2602. Output::Print(_u("%d (0x%X)"), m_value, m_value);
  2603. }
  2604. }
  2605. template<>
  2606. void EncodableOpnd<int64>::DumpEncodable() const
  2607. {
  2608. if (name != nullptr)
  2609. {
  2610. Output::Print(_u("<%s> (value: 0x%llX)"), name, m_value);
  2611. }
  2612. else if (decodedValue != 0)
  2613. {
  2614. Output::Print(_u("%lld (0x%llX) [encoded: 0x%llX]"), decodedValue, decodedValue, m_value);
  2615. }
  2616. else
  2617. {
  2618. Output::Print(_u("%lld (0x%llX)"), m_value, m_value);
  2619. }
  2620. }
  2621. ///----------------------------------------------------------------------------
  2622. ///
  2623. /// Opnd::Dump
  2624. ///
  2625. /// Dump this opnd.
  2626. ///
  2627. ///----------------------------------------------------------------------------
  2628. void
  2629. Opnd::Dump(IRDumpFlags flags, Func *func)
  2630. {
  2631. bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
  2632. bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
  2633. FloatConstType floatValue;
  2634. SymOpnd * symOpnd;
  2635. RegOpnd * regOpnd;
  2636. JnHelperMethod helperMethod;
  2637. bool dumpValueType = !SimpleForm;
  2638. switch(GetKind())
  2639. {
  2640. case OpndKindSym:
  2641. symOpnd = this->AsSymOpnd();
  2642. if(symOpnd->m_sym->IsPropertySym() && !SimpleForm)
  2643. {
  2644. symOpnd->m_sym->Dump(flags, symOpnd->GetPropertyOwnerValueType());
  2645. }
  2646. else
  2647. {
  2648. symOpnd->m_sym->Dump(flags);
  2649. }
  2650. if (symOpnd->m_sym->IsStackSym())
  2651. {
  2652. StackSym * stackSym = symOpnd->m_sym->AsStackSym();
  2653. bool hasOffset = stackSym->IsArgSlotSym()?
  2654. ((stackSym->m_offset != -1) || !stackSym->m_isInlinedArgSlot) :
  2655. (stackSym->m_offset != 0);
  2656. if (hasOffset)
  2657. {
  2658. int offset = stackSym->m_offset;
  2659. if(symOpnd->m_offset != 0)
  2660. {
  2661. Assert(static_cast<int>(offset + symOpnd->m_offset) >= offset);
  2662. offset += symOpnd->m_offset;
  2663. }
  2664. Output::Print(_u("<%d>"), offset);
  2665. }
  2666. }
  2667. else if (symOpnd->IsPropertySymOpnd() && !SimpleForm)
  2668. {
  2669. PropertySymOpnd *propertySymOpnd = symOpnd->AsPropertySymOpnd();
  2670. Output::Print(_u("<"));
  2671. if (propertySymOpnd->HasObjTypeSpecFldInfo())
  2672. {
  2673. Output::Print(_u("%u,%s%s%s%s,"), propertySymOpnd->GetObjTypeSpecFldId(), propertySymOpnd->IsPoly() ? _u("p") : _u("m"),
  2674. propertySymOpnd->IsLoadedFromProto() ? _u("~") : _u(""), propertySymOpnd->UsesFixedValue() ? _u("=") : _u(""),
  2675. propertySymOpnd->IsBeingAdded() ? _u("+") : _u(""));
  2676. }
  2677. else
  2678. {
  2679. Output::Print(_u("?,,"));
  2680. }
  2681. Output::Print(_u("%s%s,"), propertySymOpnd->MayNeedTypeCheckProtection() ?
  2682. propertySymOpnd->IsMono() ? _u("+") : _u("=") :
  2683. propertySymOpnd->IsRootObjectNonConfigurableFieldLoad() ? _u("~") : _u("-"),
  2684. propertySymOpnd->IsTypeCheckSeqCandidate() ? _u("+") : _u("-"));
  2685. if (propertySymOpnd->HasObjectTypeSym())
  2686. {
  2687. Output::Print(_u("s%d"), propertySymOpnd->GetObjectTypeSym()->m_id);
  2688. if (propertySymOpnd->IsTypeChecked())
  2689. {
  2690. Output::Print(_u("+%s"), propertySymOpnd->IsMono() ? _u("m") : _u("p"));
  2691. }
  2692. else if (propertySymOpnd->IsTypeAvailable())
  2693. {
  2694. Output::Print(_u("*"));
  2695. }
  2696. if (propertySymOpnd->IsTypeDead())
  2697. {
  2698. Output::Print(_u("!"));
  2699. }
  2700. }
  2701. else
  2702. {
  2703. Output::Print(_u("s?"));
  2704. }
  2705. if (propertySymOpnd->m_sym->AsPropertySym()->m_writeGuardSym != nullptr)
  2706. {
  2707. Output::Print(_u(",s%d"), propertySymOpnd->m_sym->AsPropertySym()->m_writeGuardSym->m_id);
  2708. if (propertySymOpnd->IsWriteGuardChecked())
  2709. {
  2710. Output::Print(_u("+"));
  2711. }
  2712. }
  2713. else
  2714. {
  2715. Output::Print(_u(",s?"));
  2716. }
  2717. if (propertySymOpnd->HasFinalType())
  2718. {
  2719. Output::Print(_u(",final:"));
  2720. this->DumpAddress((void*)propertySymOpnd->GetFinalType()->GetAddr(), /* printToConsole */ true, /* skipMaskedAddress */ false);
  2721. }
  2722. if (propertySymOpnd->GetGuardedPropOps() != nullptr)
  2723. {
  2724. Output::Print(_u(",{"));
  2725. if (func != nullptr)
  2726. {
  2727. int i = 0;
  2728. auto guardedPropOps = propertySymOpnd->GetGuardedPropOps();
  2729. FOREACH_BITSET_IN_SPARSEBV(propertyOpId, guardedPropOps)
  2730. {
  2731. if (i++ > 0)
  2732. {
  2733. Output::Print(_u(","));
  2734. }
  2735. const ObjTypeSpecFldInfo* propertyOpInfo = func->GetTopFunc()->GetGlobalObjTypeSpecFldInfo(propertyOpId);
  2736. if (!JITManager::GetJITManager()->IsOOPJITEnabled())
  2737. {
  2738. Output::Print(_u("%s"), func->GetInProcThreadContext()->GetPropertyRecord(propertyOpInfo->GetPropertyId())->GetBuffer(), propertyOpId);
  2739. }
  2740. Output::Print(_u("(%u)"), propertyOpId);
  2741. if (propertyOpInfo->IsLoadedFromProto())
  2742. {
  2743. Output::Print(_u("~"));
  2744. }
  2745. if (propertyOpInfo->HasFixedValue())
  2746. {
  2747. Output::Print(_u("="));
  2748. }
  2749. if (propertyOpInfo->IsBeingAdded())
  2750. {
  2751. Output::Print(_u("+"));
  2752. }
  2753. }
  2754. NEXT_BITSET_IN_SPARSEBV;
  2755. }
  2756. else
  2757. {
  2758. Output::Print(_u("(no func)"));
  2759. }
  2760. Output::Print(_u("}"));
  2761. }
  2762. if (propertySymOpnd->GetWriteGuards() != nullptr)
  2763. {
  2764. Output::Print(_u(",{"));
  2765. int i = 0;
  2766. auto writeGuards = propertySymOpnd->GetWriteGuards();
  2767. FOREACH_BITSET_IN_SPARSEBV(writeGuardSymId, writeGuards)
  2768. {
  2769. if (i++ > 0)
  2770. {
  2771. Output::Print(_u(","));
  2772. }
  2773. Output::Print(_u("s%d"), writeGuardSymId);
  2774. }
  2775. NEXT_BITSET_IN_SPARSEBV;
  2776. Output::Print(_u("}"));
  2777. }
  2778. if (propertySymOpnd->canStoreTemp)
  2779. {
  2780. Output::Print(_u(",t"));
  2781. }
  2782. Output::Print(_u(">"));
  2783. }
  2784. break;
  2785. case OpndKindReg:
  2786. regOpnd = this->AsRegOpnd();
  2787. if (regOpnd->m_sym)
  2788. {
  2789. regOpnd->m_sym->Dump(flags);
  2790. }
  2791. if(AsmDumpMode)
  2792. {
  2793. //
  2794. // Print no brackets
  2795. //
  2796. Output::Print(_u("%S"), RegNames[regOpnd->GetReg()]);
  2797. }
  2798. else
  2799. {
  2800. if (regOpnd->GetReg() != RegNOREG)
  2801. {
  2802. Output::Print(_u("(%S)"), RegNames[regOpnd->GetReg()]);
  2803. }
  2804. if (regOpnd->m_isTempLastUse)
  2805. {
  2806. Output::Print(_u("[isTempLastUse]"));
  2807. }
  2808. StackSym *sym = regOpnd->GetStackSym();
  2809. if (sym && func)
  2810. {
  2811. if (sym == func->GetScriptContextSym())
  2812. {
  2813. Output::Print(_u("[ScriptContext]"));
  2814. }
  2815. else if (sym == func->GetFuncObjSym())
  2816. {
  2817. Output::Print(_u("[FuncObj]"));
  2818. }
  2819. else if (sym == func->GetFunctionBodySym())
  2820. {
  2821. Output::Print(_u("[FunctionBody]"));
  2822. }
  2823. }
  2824. if(regOpnd->IsArrayRegOpnd())
  2825. {
  2826. if(dumpValueType)
  2827. {
  2828. // Dump the array value type before the associated syms
  2829. DumpValueType();
  2830. dumpValueType = false;
  2831. }
  2832. const ArrayRegOpnd *const arrayRegOpnd = regOpnd->AsArrayRegOpnd();
  2833. if(arrayRegOpnd->HeadSegmentSym())
  2834. {
  2835. Output::Print(_u("[seg: "));
  2836. arrayRegOpnd->HeadSegmentSym()->Dump();
  2837. Output::Print(_u("]"));
  2838. }
  2839. if(arrayRegOpnd->HeadSegmentLengthSym())
  2840. {
  2841. Output::Print(_u("[segLen: "));
  2842. arrayRegOpnd->HeadSegmentLengthSym()->Dump();
  2843. Output::Print(_u("]"));
  2844. }
  2845. if(arrayRegOpnd->LengthSym() && arrayRegOpnd->LengthSym() != arrayRegOpnd->HeadSegmentLengthSym())
  2846. {
  2847. Output::Print(_u("[len: "));
  2848. arrayRegOpnd->LengthSym()->Dump();
  2849. Output::Print(_u("]"));
  2850. }
  2851. if(arrayRegOpnd->EliminatedLowerBoundCheck() || arrayRegOpnd->EliminatedUpperBoundCheck())
  2852. {
  2853. Output::Print(_u("["));
  2854. if(arrayRegOpnd->EliminatedLowerBoundCheck())
  2855. {
  2856. Output::Print(_u(">"));
  2857. }
  2858. if(arrayRegOpnd->EliminatedUpperBoundCheck())
  2859. {
  2860. Output::Print(_u("<"));
  2861. }
  2862. Output::Print(_u("]"));
  2863. }
  2864. }
  2865. }
  2866. break;
  2867. case OpndKindInt64Const:
  2868. {
  2869. Int64ConstOpnd * intConstOpnd = this->AsInt64ConstOpnd();
  2870. intConstOpnd->DumpEncodable();
  2871. break;
  2872. }
  2873. case OpndKindIntConst:
  2874. {
  2875. IntConstOpnd * intConstOpnd = this->AsIntConstOpnd();
  2876. intConstOpnd->DumpEncodable();
  2877. break;
  2878. }
  2879. case OpndKindRegBV:
  2880. {
  2881. RegBVOpnd * regBVOpnd = this->AsRegBVOpnd();
  2882. regBVOpnd->m_value.Dump();
  2883. break;
  2884. }
  2885. case OpndKindHelperCall:
  2886. helperMethod = this->AsHelperCallOpnd()->m_fnHelper;
  2887. Output::Print(_u("%s"), IR::GetMethodName(helperMethod));
  2888. break;
  2889. case OpndKindFloatConst:
  2890. floatValue = this->AsFloatConstOpnd()->m_value;
  2891. Output::Print(_u("%G"), floatValue);
  2892. break;
  2893. case OpndKindFloat32Const:
  2894. Output::Print(_u("%G"), this->AsFloat32ConstOpnd()->m_value);
  2895. break;
  2896. case OpndKindAddr:
  2897. DumpOpndKindAddr(AsmDumpMode, func);
  2898. break;
  2899. case OpndKindIndir:
  2900. {
  2901. IndirOpnd * indirOpnd = this->AsIndirOpnd();
  2902. RegOpnd * baseOpnd = indirOpnd->GetBaseOpnd();
  2903. RegOpnd * indexOpnd = indirOpnd->GetIndexOpnd();
  2904. const int32 offset = indirOpnd->GetOffset();
  2905. Output::Print(_u("["));
  2906. if (baseOpnd != nullptr)
  2907. {
  2908. baseOpnd->Dump(flags, func);
  2909. }
  2910. else
  2911. {
  2912. Output::Print(_u("<null>"));
  2913. }
  2914. if (indexOpnd != nullptr)
  2915. {
  2916. Output::Print(_u("+"));
  2917. indexOpnd->Dump(flags, func);
  2918. if (indirOpnd->GetScale() > 0)
  2919. {
  2920. Output::Print(_u("*%d"), 1 << indirOpnd->GetScale());
  2921. }
  2922. }
  2923. if (offset != 0)
  2924. {
  2925. if (!Js::Configuration::Global.flags.DumpIRAddresses && indirOpnd->HasAddrKind())
  2926. {
  2927. Output::Print(_u("+XX"));
  2928. }
  2929. else
  2930. {
  2931. const auto sign = offset >= 0 ? _u("+") : _u("");
  2932. if (AsmDumpMode)
  2933. {
  2934. Output::Print(_u("%sXXXX%04d"), sign, offset & 0xffff);
  2935. }
  2936. else
  2937. {
  2938. Output::Print(_u("%s%d"), sign, offset);
  2939. }
  2940. }
  2941. }
  2942. if (indirOpnd->GetDescription())
  2943. {
  2944. Output::Print(_u(" <%s>"), indirOpnd->GetDescription());
  2945. }
  2946. if (indirOpnd->HasAddrKind())
  2947. {
  2948. INT_PTR address = (INT_PTR)indirOpnd->GetOriginalAddress();
  2949. Output::Print(_u(" <"));
  2950. const size_t BUFFER_LEN = 128;
  2951. char16 buffer[BUFFER_LEN];
  2952. GetAddrDescription(buffer, BUFFER_LEN, (void *)address, indirOpnd->GetAddrKind(), AsmDumpMode, /*printToConsole */ true, func, /* skipMaskedAddress */true);
  2953. Output::Print(_u("%s"), buffer);
  2954. Output::Print(_u(">"));
  2955. }
  2956. Output::Print(_u("]"));
  2957. break;
  2958. }
  2959. case IR::OpndKindList:
  2960. {
  2961. IR::ListOpnd* list = this->AsListOpnd();
  2962. Output::Print(_u("{"));
  2963. int count = list->Count();
  2964. list->Map([flags, func, count](int i, IR::Opnd* opnd)
  2965. {
  2966. opnd->Dump(flags, func);
  2967. if (i + 1 < count)
  2968. {
  2969. Output::Print(_u(","));
  2970. }
  2971. });
  2972. Output::Print(_u("}"));
  2973. break;
  2974. }
  2975. case OpndKindMemRef:
  2976. {
  2977. DumpOpndKindMemRef(AsmDumpMode, func);
  2978. break;
  2979. }
  2980. case OpndKindLabel:
  2981. {
  2982. LabelOpnd * labelOpnd = this->AsLabelOpnd();
  2983. LabelInstr * labelInstr = labelOpnd->GetLabel();
  2984. if (labelInstr == nullptr)
  2985. {
  2986. Output::Print(_u("??"));
  2987. }
  2988. else
  2989. {
  2990. Output::Print(_u("&$L%d"), labelInstr->m_id);
  2991. }
  2992. break;
  2993. }
  2994. }
  2995. if(!AsmDumpMode && dumpValueType)
  2996. {
  2997. DumpValueType();
  2998. }
  2999. if (!SimpleForm || this->GetType() != TyVar)
  3000. {
  3001. Output::Print(_u("."));
  3002. IRType_Dump(this->GetType());
  3003. }
  3004. if (this->m_isDead && !SimpleForm)
  3005. {
  3006. Output::Print(_u("!"));
  3007. }
  3008. }
  3009. ///----------------------------------------------------------------------------
  3010. ///
  3011. /// Opnd::DumpOpndKindAddr
  3012. ///
  3013. /// Dump this opnd as an address.
  3014. ///
  3015. ///----------------------------------------------------------------------------
  3016. void
  3017. Opnd::DumpOpndKindAddr(bool AsmDumpMode, Func *func)
  3018. {
  3019. const size_t BUFFER_LEN = 128;
  3020. char16 buffer[BUFFER_LEN];
  3021. GetAddrDescription(buffer, BUFFER_LEN, AsmDumpMode, true, func);
  3022. Output::Print(_u("%s"), buffer);
  3023. }
  3024. void
  3025. Opnd::DumpOpndKindMemRef(bool AsmDumpMode, Func *func)
  3026. {
  3027. MemRefOpnd *memRefOpnd = this->AsMemRefOpnd();
  3028. Output::Print(_u("["));
  3029. const size_t BUFFER_LEN = 128;
  3030. char16 buffer[BUFFER_LEN];
  3031. // TODO: michhol, make this intptr_t
  3032. GetAddrDescription(buffer, BUFFER_LEN, (void*)memRefOpnd->GetMemLoc(), memRefOpnd->GetAddrKind(), AsmDumpMode, true, func);
  3033. Output::Print(_u("%s"), buffer);
  3034. Output::Print(_u("]"));
  3035. }
  3036. /**
  3037. WriteToBuffer
  3038. Write <fmt> with applicable replacements into <buffer>.
  3039. Subtract the number of characters written from <count>, and increment the address
  3040. <buffer> so that subsequent calls to this function will continue writing at the point
  3041. in the buffer where this function left off and will respect the maximum length specified
  3042. by count.
  3043. @param buffer
  3044. A pointer to a buffer which will hold the result.
  3045. @param count
  3046. The maximum number of characters that should be returned in <buffer>.
  3047. @param fmt
  3048. A format string.
  3049. @param ...
  3050. Additional parameters to be passed to the formatter.
  3051. */
  3052. void
  3053. Opnd::WriteToBuffer(_Outptr_result_buffer_(*count) char16 **buffer, size_t *count, const char16 *fmt, ...)
  3054. {
  3055. va_list argptr;
  3056. va_start(argptr, fmt);
  3057. int len = _vsnwprintf_s(*buffer, *count, _TRUNCATE, fmt, argptr);
  3058. *count -= len;
  3059. *buffer += len;
  3060. va_end(argptr);
  3061. }
  3062. void
  3063. Opnd::GetAddrDescription(__out_ecount(count) char16 *const description, const size_t count,
  3064. void * address, IR::AddrOpndKind addressKind, bool AsmDumpMode, bool printToConsole, Func *func, bool skipMaskedAddress)
  3065. {
  3066. char16 *buffer = description;
  3067. size_t n = count;
  3068. if (address)
  3069. {
  3070. switch (addressKind)
  3071. {
  3072. case IR::AddrOpndKindConstantAddress:
  3073. {
  3074. #ifdef TARGET_64
  3075. char16 const * format = _u("0x%012I64X");
  3076. #else
  3077. char16 const * format = _u("0x%08X");
  3078. #endif
  3079. WriteToBuffer(&buffer, &n, format, address);
  3080. }
  3081. break;
  3082. case IR::AddrOpndKindDynamicVar:
  3083. if (Js::TaggedInt::Is(address))
  3084. {
  3085. #ifdef TARGET_64
  3086. char16 const * format = _u("0x%012I64X (value: %d)");
  3087. #else
  3088. char16 const * format = _u("0x%08X (value: %d)");
  3089. #endif
  3090. WriteToBuffer(&buffer, &n, format, address, Js::TaggedInt::ToInt32(address));
  3091. }
  3092. #if FLOATVAR
  3093. else if (Js::JavascriptNumber::Is_NoTaggedIntCheck(address))
  3094. #else
  3095. else if (!func->IsOOPJIT() && Js::JavascriptNumber::Is_NoTaggedIntCheck(address))
  3096. #endif
  3097. {
  3098. WriteToBuffer(&buffer, &n, _u(" (value: %f)"), Js::JavascriptNumber::GetValue(address));
  3099. }
  3100. else
  3101. {
  3102. DumpAddress(address, printToConsole, skipMaskedAddress);
  3103. // TODO: michhol OOP JIT, fix dumping these
  3104. if (func->IsOOPJIT())
  3105. {
  3106. WriteToBuffer(&buffer, &n, _u(" (unknown)"));
  3107. }
  3108. else
  3109. {
  3110. switch (Js::RecyclableObject::FromVar(address)->GetTypeId())
  3111. {
  3112. case Js::TypeIds_Boolean:
  3113. WriteToBuffer(&buffer, &n, Js::JavascriptBoolean::FromVar(address)->GetValue() ? _u(" (true)") : _u(" (false)"));
  3114. break;
  3115. case Js::TypeIds_String:
  3116. WriteToBuffer(&buffer, &n, _u(" (\"%s\")"), Js::JavascriptString::FromVar(address)->GetSz());
  3117. break;
  3118. case Js::TypeIds_Number:
  3119. WriteToBuffer(&buffer, &n, _u(" (value: %f)"), Js::JavascriptNumber::GetValue(address));
  3120. break;
  3121. case Js::TypeIds_Undefined:
  3122. WriteToBuffer(&buffer, &n, _u(" (undefined)"));
  3123. break;
  3124. case Js::TypeIds_Null:
  3125. WriteToBuffer(&buffer, &n, _u(" (null)"));
  3126. break;
  3127. case Js::TypeIds_GlobalObject:
  3128. WriteToBuffer(&buffer, &n, _u(" (GlobalObject)"));
  3129. break;
  3130. case Js::TypeIds_UndeclBlockVar:
  3131. WriteToBuffer(&buffer, &n, _u(" (UndeclBlockVar)"));
  3132. break;
  3133. case Js::TypeIds_Function:
  3134. DumpFunctionInfo(&buffer, &n, ((Js::JavascriptFunction *)address)->GetFunctionInfo(), printToConsole, _u("FunctionObject"));
  3135. break;
  3136. default:
  3137. WriteToBuffer(&buffer, &n, _u(" (DynamicObject)"));
  3138. break;
  3139. }
  3140. }
  3141. }
  3142. break;
  3143. case IR::AddrOpndKindConstantVar:
  3144. {
  3145. #ifdef TARGET_64
  3146. char16 const * format = _u("0x%012I64X%s");
  3147. #else
  3148. char16 const * format = _u("0x%08X%s");
  3149. #endif
  3150. char16 const * addressName = _u("");
  3151. if (address == Js::JavascriptArray::MissingItem)
  3152. {
  3153. addressName = _u(" (MissingItem)");
  3154. }
  3155. #if FLOATVAR
  3156. else if (address == (Js::Var)Js::FloatTag_Value)
  3157. {
  3158. addressName = _u(" (FloatTag)");
  3159. }
  3160. #endif
  3161. WriteToBuffer(&buffer, &n, format, address, addressName);
  3162. break;
  3163. }
  3164. case IR::AddrOpndKindDynamicScriptContext:
  3165. Assert(func == nullptr || (intptr_t)address == func->GetScriptContextInfo()->GetAddr());
  3166. // The script context pointer is unstable allocated from the CRT
  3167. DumpAddress(address, printToConsole, skipMaskedAddress);
  3168. WriteToBuffer(&buffer, &n, _u(" (ScriptContext)"));
  3169. break;
  3170. case IR::AddrOpndKindDynamicCharStringCache:
  3171. Assert(func == nullptr || (intptr_t)address == func->GetScriptContextInfo()->GetCharStringCacheAddr());
  3172. DumpAddress(address, printToConsole, skipMaskedAddress);
  3173. WriteToBuffer(&buffer, &n, _u(" (CharStringCache)"));
  3174. break;
  3175. case IR::AddrOpndKindDynamicBailOutRecord:
  3176. DumpAddress(address, printToConsole, skipMaskedAddress);
  3177. WriteToBuffer(&buffer, &n, _u(" (BailOutRecord)"));
  3178. break;
  3179. case IR::AddrOpndKindDynamicInlineCache:
  3180. DumpAddress(address, printToConsole, skipMaskedAddress);
  3181. WriteToBuffer(&buffer, &n, _u(" (InlineCache)"));
  3182. break;
  3183. case IR::AddrOpndKindDynamicIsInstInlineCacheFunctionRef:
  3184. DumpAddress(address, printToConsole, skipMaskedAddress);
  3185. WriteToBuffer(&buffer, &n, _u(" (&IsInstInlineCache.function)"));
  3186. break;
  3187. case IR::AddrOpndKindDynamicIsInstInlineCacheTypeRef:
  3188. DumpAddress(address, printToConsole, skipMaskedAddress);
  3189. WriteToBuffer(&buffer, &n, _u(" (&IsInstInlineCache.type)"));
  3190. break;
  3191. case IR::AddrOpndKindDynamicIsInstInlineCacheResultRef:
  3192. DumpAddress(address, printToConsole, skipMaskedAddress);
  3193. WriteToBuffer(&buffer, &n, _u(" (&IsInstInlineCache.result)"));
  3194. break;
  3195. case AddrOpndKindDynamicGuardValueRef:
  3196. DumpAddress(address, printToConsole, skipMaskedAddress);
  3197. WriteToBuffer(&buffer, &n, _u(" (&GuardValue)"));
  3198. break;
  3199. case AddrOpndKindDynamicAuxSlotArrayRef:
  3200. DumpAddress(address, printToConsole, skipMaskedAddress);
  3201. WriteToBuffer(&buffer, &n, _u(" (&AuxSlotArray)"));
  3202. break;
  3203. case AddrOpndKindDynamicPropertySlotRef:
  3204. DumpAddress(address, printToConsole, skipMaskedAddress);
  3205. WriteToBuffer(&buffer, &n, _u(" (&PropertySlot)"));
  3206. break;
  3207. case AddrOpndKindDynamicBailOutKindRef:
  3208. DumpAddress(address, printToConsole, skipMaskedAddress);
  3209. WriteToBuffer(&buffer, &n, _u(" (&BailOutKind)"));
  3210. break;
  3211. case AddrOpndKindDynamicArrayCallSiteInfo:
  3212. DumpAddress(address, printToConsole, skipMaskedAddress);
  3213. WriteToBuffer(&buffer, &n, _u(" (ArrayCallSiteInfo)"));
  3214. break;
  3215. case AddrOpndKindDynamicTypeCheckGuard:
  3216. DumpAddress(address, printToConsole, skipMaskedAddress);
  3217. WriteToBuffer(&buffer, &n, _u(" (TypeCheckGuard)"));
  3218. break;
  3219. case AddrOpndKindDynamicRecyclerAllocatorEndAddressRef:
  3220. DumpAddress(address, printToConsole, skipMaskedAddress);
  3221. WriteToBuffer(&buffer, &n, _u(" (&RecyclerAllocatorEndAddress)"));
  3222. break;
  3223. case AddrOpndKindDynamicAuxBufferRef:
  3224. DumpAddress(address, printToConsole, skipMaskedAddress);
  3225. WriteToBuffer(&buffer, &n, _u(" (AuxBufferRef)"));
  3226. break;
  3227. case AddrOpndKindDynamicRecyclerAllocatorFreeListRef:
  3228. DumpAddress(address, printToConsole, skipMaskedAddress);
  3229. WriteToBuffer(&buffer, &n, _u(" (&RecyclerAllocatorFreeList)"));
  3230. break;
  3231. case IR::AddrOpndKindDynamicFunctionInfo:
  3232. DumpAddress(address, printToConsole, skipMaskedAddress);
  3233. if (func->IsOOPJIT())
  3234. {
  3235. // TODO: OOP JIT, dump more info
  3236. WriteToBuffer(&buffer, &n, _u(" (FunctionInfo)"));
  3237. }
  3238. else
  3239. {
  3240. DumpFunctionInfo(&buffer, &n, (Js::FunctionInfo *)address, printToConsole);
  3241. }
  3242. break;
  3243. case IR::AddrOpndKindDynamicFunctionBody:
  3244. DumpAddress(address, printToConsole, skipMaskedAddress);
  3245. if (func->IsOOPJIT())
  3246. {
  3247. // TODO: OOP JIT, dump more info
  3248. WriteToBuffer(&buffer, &n, _u(" (FunctionBody)"));
  3249. }
  3250. else
  3251. {
  3252. DumpFunctionInfo(&buffer, &n, ((Js::FunctionBody *)address)->GetFunctionInfo(), printToConsole);
  3253. }
  3254. break;
  3255. case IR::AddrOpndKindDynamicFunctionBodyWeakRef:
  3256. DumpAddress(address, printToConsole, skipMaskedAddress);
  3257. if (func->IsOOPJIT())
  3258. {
  3259. // TODO: OOP JIT, dump more info
  3260. WriteToBuffer(&buffer, &n, _u(" (FunctionBodyWeakRef)"));
  3261. }
  3262. else
  3263. {
  3264. DumpFunctionInfo(&buffer, &n, ((RecyclerWeakReference<Js::FunctionBody> *)address)->FastGet()->GetFunctionInfo(), printToConsole, _u("FunctionBodyWeakRef"));
  3265. }
  3266. break;
  3267. case IR::AddrOpndKindDynamicFunctionEnvironmentRef:
  3268. DumpAddress(address, printToConsole, skipMaskedAddress);
  3269. DumpFunctionInfo(&buffer, &n, ((Js::ScriptFunction *)((intptr_t)address - Js::ScriptFunction::GetOffsetOfEnvironment()))->GetFunctionInfo(),
  3270. printToConsole, _u("ScriptFunctionEnvironmentRef"));
  3271. break;
  3272. case IR::AddrOpndKindDynamicVtable:
  3273. if ((INT_PTR)address == Js::ScriptContextOptimizationOverrideInfo::InvalidVtable)
  3274. {
  3275. WriteToBuffer(&buffer, &n, _u("%d (Invalid Vtable)"), Js::ScriptContextOptimizationOverrideInfo::InvalidVtable);
  3276. }
  3277. else
  3278. {
  3279. DumpAddress(address, printToConsole, skipMaskedAddress);
  3280. WriteToBuffer(&buffer, &n, _u(" (%S Vtable)"), func->GetVtableName((INT_PTR)address));
  3281. }
  3282. break;
  3283. case IR::AddrOpndKindDynamicTypeHandler:
  3284. DumpAddress(address, printToConsole, skipMaskedAddress);
  3285. WriteToBuffer(&buffer, &n, _u(" (TypeHandler)"));
  3286. break;
  3287. case IR::AddrOpndKindDynamicObjectTypeRef:
  3288. DumpAddress(address, printToConsole, skipMaskedAddress);
  3289. {
  3290. Js::RecyclableObject * dynamicObject = (Js::RecyclableObject *)((intptr_t)address - Js::RecyclableObject::GetOffsetOfType());
  3291. if (!func->IsOOPJIT() && Js::JavascriptFunction::Is(dynamicObject))
  3292. {
  3293. DumpFunctionInfo(&buffer, &n, Js::JavascriptFunction::FromVar((void *)((intptr_t)address - Js::RecyclableObject::GetOffsetOfType()))->GetFunctionInfo(),
  3294. printToConsole, _u("FunctionObjectTypeRef"));
  3295. }
  3296. else
  3297. {
  3298. // TODO: OOP JIT, dump more info
  3299. WriteToBuffer(&buffer, &n, _u(" (ObjectTypeRef)"));
  3300. }
  3301. }
  3302. break;
  3303. case IR::AddrOpndKindDynamicType:
  3304. DumpAddress(address, printToConsole, skipMaskedAddress);
  3305. // TODO: OOP JIT, dump more info
  3306. if(!func->IsOOPJIT())
  3307. {
  3308. Js::TypeId typeId = ((Js::Type*)address)->GetTypeId();
  3309. switch (typeId)
  3310. {
  3311. case Js::TypeIds_Number:
  3312. WriteToBuffer(&buffer, &n, _u(" (Type: StaticNumber)"));
  3313. break;
  3314. case Js::TypeIds_String:
  3315. WriteToBuffer(&buffer, &n, _u(" (Type: StaticString)"));
  3316. break;
  3317. case Js::TypeIds_Object:
  3318. WriteToBuffer(&buffer, &n, _u(" (Type: Object)"));
  3319. break;
  3320. case Js::TypeIds_RegEx:
  3321. WriteToBuffer(&buffer, &n, _u(" (Type: Regex)"));
  3322. break;
  3323. case Js::TypeIds_Array:
  3324. WriteToBuffer(&buffer, &n, _u(" (Type: Array)"));
  3325. break;
  3326. case Js::TypeIds_NativeIntArray:
  3327. WriteToBuffer(&buffer, &n, _u(" (Type: NativeIntArray)"));
  3328. break;
  3329. case Js::TypeIds_NativeFloatArray:
  3330. WriteToBuffer(&buffer, &n, _u(" (Type: NativeFltArray)"));
  3331. break;
  3332. default:
  3333. WriteToBuffer(&buffer, &n, _u(" (Type: Id %d)"), typeId);
  3334. break;
  3335. }
  3336. }
  3337. break;
  3338. case AddrOpndKindDynamicFrameDisplay:
  3339. DumpAddress(address, printToConsole, skipMaskedAddress);
  3340. if (!func->IsOOPJIT())
  3341. {
  3342. Js::FrameDisplay * frameDisplay = (Js::FrameDisplay *)address;
  3343. WriteToBuffer(&buffer, &n, (frameDisplay->GetStrictMode() ? _u(" (StrictFrameDisplay len %d)") : _u(" (FrameDisplay len %d)")),
  3344. frameDisplay->GetLength());
  3345. }
  3346. else
  3347. {
  3348. WriteToBuffer(&buffer, &n, _u(" (FrameDisplay)"));
  3349. }
  3350. break;
  3351. case AddrOpndKindSz:
  3352. WriteToBuffer(&buffer, &n, wcslen((char16 const *)address) > 30 ? _u("\"%.30s...\"") : _u("\"%.30s\""), address);
  3353. break;
  3354. case AddrOpndKindDynamicFloatRef:
  3355. DumpAddress(address, printToConsole, skipMaskedAddress);
  3356. WriteToBuffer(&buffer, &n, _u(" (&(float)%f)"), *(float *)address);
  3357. break;
  3358. case AddrOpndKindDynamicDoubleRef:
  3359. DumpAddress(address, printToConsole, skipMaskedAddress);
  3360. WriteToBuffer(&buffer, &n, _u(" (&(double)%f)"), *(double *)address);
  3361. break;
  3362. case AddrOpndKindForInCache:
  3363. DumpAddress(address, printToConsole, skipMaskedAddress);
  3364. WriteToBuffer(&buffer, &n, _u(" (EnumeratorCache)"));
  3365. break;
  3366. case AddrOpndKindForInCacheType:
  3367. DumpAddress(address, printToConsole, skipMaskedAddress);
  3368. WriteToBuffer(&buffer, &n, _u(" (&EnumeratorCache->type)"));
  3369. break;
  3370. case AddrOpndKindForInCacheData:
  3371. DumpAddress(address, printToConsole, skipMaskedAddress);
  3372. WriteToBuffer(&buffer, &n, _u(" (&EnumeratorCache->data)"));
  3373. break;
  3374. case AddrOpndKindDynamicNativeCodeDataRef:
  3375. DumpAddress(address, printToConsole, skipMaskedAddress);
  3376. WriteToBuffer(&buffer, &n, _u(" (&NativeCodeData)"));
  3377. break;
  3378. case AddrOpndKindWriteBarrierCardTable:
  3379. DumpAddress(address, printToConsole, skipMaskedAddress);
  3380. WriteToBuffer(&buffer, &n, _u(" (&WriteBarrierCardTable)"));
  3381. break;
  3382. default:
  3383. DumpAddress(address, printToConsole, skipMaskedAddress);
  3384. if ((intptr_t)address == func->GetThreadContextInfo()->GetNullFrameDisplayAddr())
  3385. {
  3386. WriteToBuffer(&buffer, &n, _u(" (NullFrameDisplay)"));
  3387. }
  3388. else if ((intptr_t)address == func->GetThreadContextInfo()->GetStrictNullFrameDisplayAddr())
  3389. {
  3390. WriteToBuffer(&buffer, &n, _u(" (StrictNullFrameDisplay)"));
  3391. }
  3392. else if ((intptr_t)address == func->GetScriptContextInfo()->GetNumberAllocatorAddr())
  3393. {
  3394. WriteToBuffer(&buffer, &n, _u(" (NumberAllocator)"));
  3395. }
  3396. else if ((intptr_t)address == func->GetScriptContextInfo()->GetRecyclerAddr())
  3397. {
  3398. WriteToBuffer(&buffer, &n, _u(" (Recycler)"));
  3399. }
  3400. else if (func->GetWorkItem()->Type() == JsFunctionType && (intptr_t)address == func->GetWorkItem()->GetCallsCountAddress())
  3401. {
  3402. WriteToBuffer(&buffer, &n, _u(" (&CallCount)"));
  3403. }
  3404. else if ((intptr_t)address == func->GetThreadContextInfo()->GetImplicitCallFlagsAddr())
  3405. {
  3406. WriteToBuffer(&buffer, &n, _u(" (&ImplicitCallFlags)"));
  3407. }
  3408. else if ((intptr_t)address == func->GetThreadContextInfo()->GetDisableImplicitFlagsAddr())
  3409. {
  3410. WriteToBuffer(&buffer, &n, _u(" (&DisableImplicitCallFlags)"));
  3411. }
  3412. else if ((intptr_t)address == func->GetThreadContextInfo()->GetThreadStackLimitAddr())
  3413. {
  3414. WriteToBuffer(&buffer, &n, _u(" (&StackLimit)"));
  3415. }
  3416. else if (func->CanAllocInPreReservedHeapPageSegment() &&
  3417. #if ENABLE_OOP_NATIVE_CODEGEN
  3418. (func->IsOOPJIT()
  3419. ? func->GetOOPThreadContext()->GetPreReservedSectionAllocator()->IsPreReservedEndAddress(address)
  3420. : func->GetInProcThreadContext()->GetPreReservedVirtualAllocator()->IsPreReservedEndAddress(address)
  3421. )
  3422. #else
  3423. func->GetInProcThreadContext()->GetPreReservedVirtualAllocator()->IsPreReservedEndAddress(address)
  3424. #endif
  3425. )
  3426. {
  3427. WriteToBuffer(&buffer, &n, _u(" (PreReservedCodeSegmentEnd)"));
  3428. }
  3429. else if ((intptr_t)address == func->GetScriptContextInfo()->GetSideEffectsAddr())
  3430. {
  3431. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_SideEffects)"));
  3432. }
  3433. else if ((intptr_t)address == func->GetScriptContextInfo()->GetArraySetElementFastPathVtableAddr())
  3434. {
  3435. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_ArraySetElementFastPathVtable)"));
  3436. }
  3437. else if ((intptr_t)address == func->GetScriptContextInfo()->GetIntArraySetElementFastPathVtableAddr())
  3438. {
  3439. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_IntArraySetElementFastPathVtable)"));
  3440. }
  3441. else if ((intptr_t)address == func->GetScriptContextInfo()->GetFloatArraySetElementFastPathVtableAddr())
  3442. {
  3443. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_FloatArraySetElementFastPathVtable)"));
  3444. }
  3445. else
  3446. {
  3447. WriteToBuffer(&buffer, &n, _u(" (Unknown)"));
  3448. }
  3449. }
  3450. }
  3451. else
  3452. {
  3453. WriteToBuffer(&buffer, &n, _u("(NULL)"));
  3454. }
  3455. }
  3456. /**
  3457. GetAddrDescription
  3458. Determine the type of the address and place at most <count> wide chars of the
  3459. description into <description>.
  3460. Force null termination of <description>.
  3461. @param description
  3462. A buffer which will hold the description.
  3463. @param count
  3464. The maximum number of characters that should be returned in <description>.
  3465. @param AsmDumpMode
  3466. @param func
  3467. */
  3468. void
  3469. Opnd::GetAddrDescription(__out_ecount(count) char16 *const description, const size_t count, bool AsmDumpMode,
  3470. bool printToConsole, Func *func)
  3471. {
  3472. char16 *buffer = description;
  3473. size_t n = count;
  3474. IR::AddrOpnd * addrOpnd = this->AsAddrOpnd();
  3475. Js::Var address;
  3476. bool isEncoded = false;
  3477. if (addrOpnd->decodedValue != 0)
  3478. {
  3479. address = addrOpnd->decodedValue;
  3480. isEncoded = true;
  3481. }
  3482. else
  3483. {
  3484. address = addrOpnd->m_address;
  3485. }
  3486. GetAddrDescription(description, count, address, addrOpnd->GetAddrOpndKind(), AsmDumpMode, printToConsole, func);
  3487. if (isEncoded)
  3488. {
  3489. if (AsmDumpMode)
  3490. {
  3491. WriteToBuffer(&buffer, &n, _u(" [encoded]"));
  3492. }
  3493. else
  3494. {
  3495. WriteToBuffer(&buffer, &n, _u(" [encoded: 0x%08X"), addrOpnd->m_address);
  3496. }
  3497. }
  3498. description[count-1] = 0; // force null termination
  3499. }
  3500. void
  3501. Opnd::Dump()
  3502. {
  3503. this->Dump(IRDumpFlags_None, nullptr);
  3504. }
  3505. #endif
  3506. } // namespace IR