IR.cpp 128 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540
  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. void
  9. Instr::Init(Js::OpCode opcode, IRKind kind, Func * func)
  10. {
  11. Assert(!OpCodeAttr::ByteCodeOnly(opcode));
  12. this->m_opcode = opcode;
  13. this->m_kind = kind;
  14. this->m_func = func;
  15. #ifdef BAILOUT_INJECTION
  16. this->bailOutByteCodeLocation = (uint)-1;
  17. #endif
  18. }
  19. uint32
  20. Instr::GetByteCodeOffset() const
  21. {
  22. Assert(m_func->HasByteCodeOffset());
  23. return m_number;
  24. }
  25. void
  26. Instr::SetByteCodeOffset(uint32 offset)
  27. {
  28. Assert(m_func->HasByteCodeOffset());
  29. Assert(m_number == Js::Constants::NoByteCodeOffset);
  30. m_number = offset;
  31. }
  32. void
  33. Instr::SetByteCodeOffset(IR::Instr * instr)
  34. {
  35. SetByteCodeOffset(instr->GetByteCodeOffset());
  36. }
  37. void
  38. Instr::ClearByteCodeOffset()
  39. {
  40. Assert(m_func->HasByteCodeOffset());
  41. m_number = Js::Constants::NoByteCodeOffset;
  42. }
  43. uint32
  44. Instr::GetNumber() const
  45. {
  46. Assert(m_func->HasInstrNumber());
  47. return m_number;
  48. }
  49. void
  50. Instr::SetNumber(uint32 number)
  51. {
  52. Assert(m_func->HasInstrNumber());
  53. m_number = number;
  54. }
  55. bool
  56. Instr::IsPlainInstr() const
  57. {
  58. return this->GetKind() == IR::InstrKindInstr;
  59. }
  60. bool
  61. Instr::DoStackArgsOpt(Func *topFunc) const
  62. {
  63. return this->usesStackArgumentsObject && m_func->IsStackArgsEnabled();
  64. }
  65. bool
  66. Instr::HasTypeCheckBailOut() const
  67. {
  68. return this->HasBailOutInfo() && IR::IsTypeCheckBailOutKind(this->GetBailOutKind());
  69. }
  70. bool
  71. Instr::HasEquivalentTypeCheckBailOut() const
  72. {
  73. return this->HasBailOutInfo() && IR::IsEquivalentTypeCheckBailOutKind(this->GetBailOutKind());
  74. }
  75. void
  76. Instr::ChangeEquivalentToMonoTypeCheckBailOut()
  77. {
  78. Assert(this->HasEquivalentTypeCheckBailOut());
  79. this->SetBailOutKind(IR::EquivalentToMonoTypeCheckBailOutKind(this->GetBailOutKind()));
  80. }
  81. intptr_t
  82. Instr::TryOptimizeInstrWithFixedDataProperty(IR::Instr **pInstr, GlobOpt * globopt)
  83. {
  84. IR::Instr *&instr = *pInstr;
  85. Assert(OpCodeAttr::CanLoadFixedFields(instr->m_opcode));
  86. IR::Opnd * src1 = instr->GetSrc1();
  87. Assert(src1 && src1->IsSymOpnd() && src1->AsSymOpnd()->IsPropertySymOpnd());
  88. IR::PropertySymOpnd * propSymOpnd = src1->AsSymOpnd()->AsPropertySymOpnd();
  89. if (propSymOpnd->HasFixedValue() && !propSymOpnd->IsPoly())
  90. {
  91. intptr_t fixedValue = propSymOpnd->GetFieldValueAsFixedData();
  92. Assert(instr->IsProfiledInstr());
  93. ValueType valType = instr->AsProfiledInstr()->u.FldInfo().valueType;
  94. if (fixedValue && ((Js::TaggedInt::Is(fixedValue) && (valType.IsUninitialized() || valType.IsLikelyInt())) || PHASE_ON1(Js::FixDataVarPropsPhase)))
  95. {
  96. // Change Ld[Root]Fld to CheckFixedFld, which doesn't need a dst.
  97. instr->m_opcode = Js::OpCode::CheckFixedFld;
  98. IR::RegOpnd* dataValueDstOpnd = instr->UnlinkDst()->AsRegOpnd();
  99. if (globopt)
  100. {
  101. globopt->GenerateBailAtOperation(&instr, !propSymOpnd->HasEquivalentTypeSet() ? IR::BailOutFailedFixedFieldTypeCheck : IR::BailOutFailedEquivalentFixedFieldTypeCheck);
  102. }
  103. else
  104. {
  105. instr = instr->ConvertToBailOutInstr(instr, !propSymOpnd->HasEquivalentTypeSet() ? IR::BailOutFailedFixedFieldTypeCheck : IR::BailOutFailedEquivalentFixedFieldTypeCheck);
  106. }
  107. IR::Instr* loadInstr = IR::Instr::NewConstantLoad(dataValueDstOpnd, (intptr_t)fixedValue, valType, instr->m_func);
  108. OUTPUT_VERBOSE_TRACE(Js::UseFixedDataPropsPhase,
  109. _u("FixedFields: Replacing the source (fixed Data prop) with property id %u with 0x%x .\n"),
  110. propSymOpnd->GetPropertyId(), fixedValue);
  111. instr->InsertAfter(loadInstr);
  112. propSymOpnd->SetUsesFixedValue(true);
  113. return fixedValue;
  114. }
  115. }
  116. return 0;
  117. }
  118. ///----------------------------------------------------------------------------
  119. ///
  120. /// Instr::IsEqual
  121. /// Check if this instruction is the same instruction as compareInstr. Two
  122. /// instructions are equal if kind, opcode, dst, src1 and src2 from both instrs
  123. /// are the same.
  124. ///
  125. ///----------------------------------------------------------------------------
  126. bool
  127. Instr::IsEqual(IR::Instr *compareInstr) const
  128. {
  129. Assert(compareInstr);
  130. if (this->GetKind() == compareInstr->GetKind()
  131. && this->m_opcode == compareInstr->m_opcode)
  132. {
  133. IR::Opnd *dst = this->GetDst();
  134. IR::Opnd *src1 = this->GetSrc1();
  135. IR::Opnd *src2 = this->GetSrc2();
  136. IR::Opnd *compareDst = compareInstr->GetDst();
  137. IR::Opnd *compareSrc1 = compareInstr->GetSrc1();
  138. IR::Opnd *compareSrc2 = compareInstr->GetSrc2();
  139. // when both dst and compareDst are null, they are equal, same applies to src1, src2
  140. if ((dst != compareDst) && (!dst || !compareDst || !dst->IsEqual(compareDst)))
  141. {
  142. return false;
  143. }
  144. if ((src1 != compareSrc1) && (!src1 || !compareSrc1 || !src1->IsEqual(compareSrc1)))
  145. {
  146. return false;
  147. }
  148. if ((src2 != compareSrc2) && (!src2 || !compareSrc2 || !src2->IsEqual(compareSrc2)))
  149. {
  150. return false;
  151. }
  152. return true;
  153. }
  154. else
  155. {
  156. return false;
  157. }
  158. }
  159. ///----------------------------------------------------------------------------
  160. ///
  161. /// Instr::InsertBefore
  162. ///
  163. /// Insert 'instr' before 'this' instruction.
  164. ///
  165. ///----------------------------------------------------------------------------
  166. void
  167. Instr::InsertBefore(Instr *instr)
  168. {
  169. Assert(!instr->IsLinked());
  170. Instr * prevInstr = this->m_prev;
  171. instr->m_prev = prevInstr;
  172. this->m_prev = instr;
  173. if (prevInstr)
  174. {
  175. prevInstr->m_next = instr;
  176. }
  177. instr->m_next = this;
  178. }
  179. ///----------------------------------------------------------------------------
  180. ///
  181. /// Instr::InsertAfter
  182. ///
  183. /// Insert 'instr' after 'this' instruction.
  184. ///
  185. ///----------------------------------------------------------------------------
  186. void
  187. Instr::InsertAfter(Instr *instr)
  188. {
  189. Assert(!instr->IsLinked());
  190. Instr * nextInstr = this->m_next;
  191. instr->m_next = nextInstr;
  192. this->m_next = instr;
  193. if (nextInstr)
  194. {
  195. nextInstr->m_prev = instr;
  196. }
  197. instr->m_prev = this;
  198. }
  199. ///----------------------------------------------------------------------------
  200. ///
  201. /// Instr::InsertRangeBefore
  202. ///
  203. ///----------------------------------------------------------------------------
  204. void
  205. Instr::InsertRangeBefore(Instr *startInstr, Instr *endInstr)
  206. {
  207. Instr * prevInstr = this->m_prev;
  208. startInstr->m_prev = prevInstr;
  209. this->m_prev = endInstr;
  210. if (prevInstr)
  211. {
  212. prevInstr->m_next = startInstr;
  213. }
  214. endInstr->m_next = this;
  215. }
  216. ///----------------------------------------------------------------------------
  217. ///
  218. /// Instr::InsertMultipleBefore - Inserts multiple instr
  219. ///
  220. ///----------------------------------------------------------------------------
  221. void
  222. Instr::InsertMultipleBefore(Instr *endInstr)
  223. {
  224. Instr *startInstr = endInstr->m_prev;
  225. if (startInstr) // more than one instruction to insert
  226. {
  227. while (startInstr->m_prev)
  228. {
  229. startInstr = startInstr->m_prev;
  230. }
  231. return this->InsertRangeBefore(startInstr, endInstr);
  232. }
  233. return this->InsertBefore(endInstr);
  234. }
  235. ///----------------------------------------------------------------------------
  236. ///
  237. /// Instr::InsertRangeAfter
  238. ///
  239. ///----------------------------------------------------------------------------
  240. void
  241. Instr::InsertRangeAfter(Instr *startInstr, Instr *endInstr)
  242. {
  243. Instr * nextInstr = this->m_next;
  244. endInstr->m_next = nextInstr;
  245. this->m_next = startInstr;
  246. if (nextInstr)
  247. {
  248. nextInstr->m_prev = endInstr;
  249. }
  250. startInstr->m_prev = this;
  251. }
  252. ///----------------------------------------------------------------------------
  253. ///
  254. /// Instr::InsertMultipleAfter - Inserts multiple instr
  255. ///
  256. ///----------------------------------------------------------------------------
  257. void
  258. Instr::InsertMultipleAfter(Instr *endInstr)
  259. {
  260. Instr *startInstr = endInstr->m_prev;
  261. if (startInstr) //more than one instruction to insert
  262. {
  263. while (startInstr->m_prev)
  264. {
  265. startInstr = startInstr->m_prev;
  266. }
  267. return this->InsertRangeAfter(startInstr, endInstr);
  268. }
  269. return this->InsertAfter(endInstr);
  270. }
  271. ///----------------------------------------------------------------------------
  272. ///
  273. /// Instr::Free
  274. ///
  275. /// Free this instruction by putting it on a free list.
  276. ///
  277. ///----------------------------------------------------------------------------
  278. void
  279. Instr::Free()
  280. {
  281. AssertMsg(!this->IsLabelInstr() || !this->AsLabelInstr()->m_hasNonBranchRef,
  282. "Cannot free label with non-branch reference");
  283. switch (this->GetKind())
  284. {
  285. case InstrKindBranch:
  286. {
  287. IR::BranchInstr *branchInstr = this->AsBranchInstr();
  288. branchInstr->ClearTarget();
  289. break;
  290. }
  291. }
  292. IR::Opnd * dstOpnd = this->GetDst();
  293. if (dstOpnd)
  294. {
  295. StackSym * stackSym = dstOpnd->GetStackSym();
  296. if (stackSym)
  297. {
  298. if (stackSym->m_isSingleDef)
  299. {
  300. Assert(!stackSym->m_isEncodedConstant);
  301. if (stackSym->m_instrDef == this)
  302. {
  303. Assert(!dstOpnd->isFakeDst);
  304. if (stackSym->IsConst())
  305. {
  306. // keep the instruction around so we can get the constant value
  307. // from the symbol
  308. return;
  309. }
  310. Assert(this->m_func->GetTopFunc()->allowRemoveBailOutArgInstr || !stackSym->m_isBailOutReferenced);
  311. stackSym->m_instrDef = nullptr;
  312. }
  313. else
  314. {
  315. Assert(dstOpnd->isFakeDst);
  316. }
  317. }
  318. else
  319. {
  320. // Encoded constants are not single-defs anymore, and therefore not isConst.
  321. Assert((!stackSym->m_isConst && stackSym->constantValue == 0)
  322. || (stackSym->m_isEncodedConstant && stackSym->constantValue != 0));
  323. }
  324. }
  325. }
  326. ClearBailOutInfo();
  327. JitAdelete(this->m_func->m_alloc, this);
  328. }
  329. ///----------------------------------------------------------------------------
  330. ///
  331. /// Instr::Unlink
  332. ///
  333. /// Unlink this instr from the instr list.
  334. ///
  335. ///----------------------------------------------------------------------------
  336. void
  337. Instr::Unlink()
  338. {
  339. m_prev->m_next = m_next;
  340. if (m_next)
  341. {
  342. m_next->m_prev = m_prev;
  343. }
  344. else
  345. {
  346. Assert(this == this->m_func->m_tailInstr);
  347. }
  348. #if DBG_DUMP
  349. // Transferring the globOptInstrString to the next non-Label Instruction
  350. if(this->globOptInstrString != nullptr && m_next && m_next->globOptInstrString == nullptr && !m_next->IsLabelInstr())
  351. {
  352. m_next->globOptInstrString = this->globOptInstrString;
  353. }
  354. #endif
  355. #if DBG
  356. m_prev = nullptr;
  357. m_next = nullptr;
  358. #endif
  359. }
  360. ///----------------------------------------------------------------------------
  361. ///
  362. /// Instr::Remove
  363. ///
  364. /// Unlink and free this instr.
  365. ///
  366. ///----------------------------------------------------------------------------
  367. void
  368. Instr::Remove()
  369. {
  370. this->Unlink();
  371. this->Free();
  372. }
  373. void
  374. Instr::SwapOpnds()
  375. {
  376. IR::Opnd *opndTemp = m_src1;
  377. m_src1 = m_src2;
  378. m_src2 = opndTemp;
  379. }
  380. // Copy a vanilla instruction.
  381. Instr *
  382. Instr::Copy()
  383. {
  384. Instr * instrCopy;
  385. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  386. {
  387. instrCopy = BailOutInstr::New(this->m_opcode, this->GetBailOutKind(), this->GetBailOutInfo(), this->m_func);
  388. instrCopy->SetByteCodeOffset(this->GetByteCodeOffset());
  389. if (this->HasAuxBailOut())
  390. {
  391. instrCopy->hasAuxBailOut = true;
  392. instrCopy->SetAuxBailOutKind(this->GetAuxBailOutKind());
  393. }
  394. }
  395. else
  396. {
  397. switch (this->GetKind())
  398. {
  399. case InstrKindInstr:
  400. instrCopy = Instr::New(this->m_opcode, this->m_func);
  401. break;
  402. case InstrKindProfiled:
  403. instrCopy = this->AsProfiledInstr()->CopyProfiledInstr();
  404. break;
  405. case InstrKindJitProfiling:
  406. instrCopy = this->AsJitProfilingInstr()->CopyJitProfiling();
  407. break;
  408. case InstrKindPragma:
  409. instrCopy = this->AsPragmaInstr()->CopyPragma();
  410. break;
  411. default:
  412. instrCopy = nullptr;
  413. AnalysisAssertMsg(UNREACHED, "Copy of other instr kinds NYI");
  414. }
  415. }
  416. Opnd * opnd = this->GetDst();
  417. if (opnd)
  418. {
  419. instrCopy->SetDst(opnd->Copy(this->m_func));
  420. }
  421. opnd = this->GetSrc1();
  422. if (opnd)
  423. {
  424. instrCopy->SetSrc1(opnd->Copy(this->m_func));
  425. opnd = this->GetSrc2();
  426. if (opnd)
  427. {
  428. instrCopy->SetSrc2(opnd->Copy(this->m_func));
  429. }
  430. }
  431. instrCopy->isInlineeEntryInstr = this->isInlineeEntryInstr;
  432. if (this->m_func->DoMaintainByteCodeOffset())
  433. {
  434. instrCopy->SetByteCodeOffset(this->GetByteCodeOffset());
  435. }
  436. instrCopy->usesStackArgumentsObject = this->usesStackArgumentsObject;
  437. return instrCopy;
  438. }
  439. LabelInstr *
  440. LabelInstr::CloneLabel(BOOL fCreate)
  441. {
  442. Func * func = this->m_func;
  443. Cloner * cloner = func->GetCloner();
  444. IR::LabelInstr * instrLabel = nullptr;
  445. AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
  446. if (cloner->labelMap == nullptr)
  447. {
  448. if (!fCreate)
  449. {
  450. return nullptr;
  451. }
  452. cloner->labelMap = HashTable<LabelInstr*>::New(cloner->alloc, 7);
  453. }
  454. else
  455. {
  456. IR::LabelInstr ** map = cloner->labelMap->Get(this->m_id);
  457. if (map)
  458. {
  459. instrLabel = *map;
  460. }
  461. }
  462. if (instrLabel == nullptr)
  463. {
  464. if (!fCreate)
  465. {
  466. return nullptr;
  467. }
  468. if (this->IsProfiledLabelInstr())
  469. {
  470. instrLabel = IR::ProfiledLabelInstr::New(this->m_opcode, func, this->AsProfiledLabelInstr()->loopImplicitCallFlags, this->AsProfiledLabelInstr()->loopFlags);
  471. #if DBG
  472. instrLabel->AsProfiledLabelInstr()->loopNum = this->AsProfiledLabelInstr()->loopNum;
  473. #endif
  474. }
  475. else
  476. {
  477. instrLabel = IR::LabelInstr::New(this->m_opcode, func, this->isOpHelper);
  478. }
  479. instrLabel->m_isLoopTop = this->m_isLoopTop;
  480. cloner->labelMap->FindOrInsert(instrLabel, this->m_id);
  481. }
  482. return instrLabel;
  483. }
  484. ProfiledLabelInstr::ProfiledLabelInstr(JitArenaAllocator * allocator)
  485. : LabelInstr(allocator)
  486. {
  487. }
  488. ProfiledLabelInstr *
  489. ProfiledLabelInstr::New(Js::OpCode opcode, Func *func, Js::ImplicitCallFlags flags, Js::LoopFlags loopFlags)
  490. {
  491. ProfiledLabelInstr * profiledLabelInstr = JitAnew(func->m_alloc, ProfiledLabelInstr, func->m_alloc);
  492. profiledLabelInstr->Init(opcode, InstrKindProfiledLabel, func, false);
  493. profiledLabelInstr->loopImplicitCallFlags = flags;
  494. profiledLabelInstr->loopFlags = loopFlags;
  495. return profiledLabelInstr;
  496. }
  497. void
  498. BranchInstr::RetargetClonedBranch()
  499. {
  500. IR::LabelInstr * instrLabel = this->m_branchTarget->CloneLabel(false);
  501. if (instrLabel == nullptr)
  502. {
  503. // Jumping outside the cloned range. No retarget.
  504. return;
  505. }
  506. this->SetTarget(instrLabel);
  507. }
  508. PragmaInstr *
  509. PragmaInstr::ClonePragma()
  510. {
  511. return this->CopyPragma();
  512. }
  513. PragmaInstr *
  514. PragmaInstr::CopyPragma()
  515. {
  516. IR::PragmaInstr * instrPragma = IR::PragmaInstr::New(this->m_opcode, 0, this->m_func);
  517. return instrPragma;
  518. }
  519. Instr *
  520. Instr::CloneInstr() const
  521. {
  522. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  523. {
  524. return ((BailOutInstr *)this)->CloneBailOut();
  525. }
  526. IR::Instr *clone = IR::Instr::New(this->m_opcode, this->m_func);
  527. clone->isInlineeEntryInstr = this->isInlineeEntryInstr;
  528. return clone;
  529. }
  530. // Clone a vanilla instruction, replacing single-def StackSym's with new syms where appropriate.
  531. Instr *
  532. Instr::Clone()
  533. {
  534. Func * func = this->m_func;
  535. Cloner *cloner = func->GetCloner();
  536. IR::Instr * instrClone;
  537. IR::Opnd * opnd;
  538. switch (this->GetKind())
  539. {
  540. case InstrKindInstr:
  541. instrClone = this->CloneInstr();
  542. break;
  543. case InstrKindBranch:
  544. instrClone = this->AsBranchInstr()->CloneBranchInstr();
  545. break;
  546. case InstrKindProfiled:
  547. instrClone = this->AsProfiledInstr()->CloneProfiledInstr();
  548. break;
  549. case InstrKindLabel:
  550. case InstrKindProfiledLabel:
  551. instrClone = this->AsLabelInstr()->CloneLabel(true);
  552. break;
  553. case InstrKindPragma:
  554. instrClone = this->AsPragmaInstr()->ClonePragma();
  555. break;
  556. case InstrKindJitProfiling:
  557. instrClone = this->AsJitProfilingInstr()->CloneJitProfiling();
  558. break;
  559. default:
  560. AssertMsg(0, "Clone of this instr kind NYI");
  561. return nullptr;
  562. }
  563. opnd = this->GetDst();
  564. if (opnd)
  565. {
  566. instrClone->SetDst(opnd->CloneDef(func));
  567. }
  568. opnd = this->GetSrc1();
  569. if (opnd)
  570. {
  571. instrClone->SetSrc1(opnd->CloneUse(func));
  572. opnd = this->GetSrc2();
  573. if (opnd)
  574. {
  575. instrClone->SetSrc2(opnd->CloneUse(func));
  576. }
  577. }
  578. if (this->m_func->DoMaintainByteCodeOffset())
  579. {
  580. instrClone->SetByteCodeOffset(this->GetByteCodeOffset());
  581. }
  582. instrClone->usesStackArgumentsObject = this->usesStackArgumentsObject;
  583. cloner->AddInstr(this, instrClone);
  584. return instrClone;
  585. }
  586. // Clone a range of instructions.
  587. Instr *
  588. Instr::CloneRange(
  589. Instr * instrStart, Instr * instrLast, Instr * instrAfter, Lowerer *lowerer, JitArenaAllocator * alloc, bool (*fMapTest)(IR::Instr*), bool clonedInstrGetOrigArgSlotSym)
  590. {
  591. IR::Instr * instrReturn = instrAfter;
  592. Func * topFunc = instrStart->m_func->GetTopFunc();
  593. topFunc->BeginClone(lowerer, alloc);
  594. topFunc->GetCloner()->clonedInstrGetOrigArgSlotSym = clonedInstrGetOrigArgSlotSym;
  595. FOREACH_INSTR_IN_RANGE(instr, instrStart, instrLast)
  596. {
  597. Instr * instrClone = instr->Clone();
  598. instrAfter->InsertAfter(instrClone);
  599. instrAfter = instrClone;
  600. instr->isCloned = true;
  601. if (fMapTest(instrClone))
  602. {
  603. IR::LabelInstr *instrLabel = IR::LabelInstr::New(Js::OpCode::Label, instr->m_func);
  604. instrClone->InsertBefore(instrLabel);
  605. topFunc->GetCloneMap()->Item(instr, instrLabel);
  606. }
  607. }
  608. NEXT_INSTR_IN_RANGE;
  609. topFunc->EndClone();
  610. return instrReturn;
  611. }
  612. ///----------------------------------------------------------------------------
  613. ///
  614. /// Instr::MoveRangeAfter
  615. ///
  616. /// Move a range of instruction after another instruction
  617. ///
  618. ///----------------------------------------------------------------------------
  619. void
  620. Instr::MoveRangeAfter(Instr * instrStart, Instr * instrLast, Instr * instrAfter)
  621. {
  622. if (instrLast->m_next != nullptr)
  623. {
  624. instrLast->m_next->m_prev = instrStart->m_prev;
  625. }
  626. else
  627. {
  628. instrLast->m_func->m_tailInstr = instrStart->m_prev;
  629. }
  630. if (instrStart->m_prev != nullptr)
  631. {
  632. instrStart->m_prev->m_next = instrLast->m_next;
  633. }
  634. else
  635. {
  636. instrStart->m_func->m_headInstr = instrLast->m_next;
  637. }
  638. instrStart->m_prev = instrAfter;
  639. instrLast->m_next = instrAfter->m_next;
  640. if (instrAfter->m_next != nullptr)
  641. {
  642. instrAfter->m_next->m_prev = instrLast;
  643. }
  644. else
  645. {
  646. instrAfter->m_func->m_tailInstr = instrLast;
  647. }
  648. instrAfter->m_next = instrStart;
  649. }
  650. JitProfilingInstr *
  651. JitProfilingInstr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Opnd *src2Opnd, Func * func)
  652. {
  653. JitProfilingInstr * profiledInstr = JitProfilingInstr::New(opcode, dstOpnd, src1Opnd, func);
  654. profiledInstr->SetSrc2(src2Opnd);
  655. return profiledInstr;
  656. }
  657. JitProfilingInstr *
  658. JitProfilingInstr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Func * func)
  659. {
  660. Assert(func->DoSimpleJitDynamicProfile());
  661. JitProfilingInstr * profiledInstr = JitAnew(func->m_alloc, IR::JitProfilingInstr);
  662. profiledInstr->Init(opcode, InstrKindJitProfiling, func);
  663. if (dstOpnd)
  664. {
  665. profiledInstr->SetDst(dstOpnd);
  666. }
  667. if (src1Opnd)
  668. {
  669. profiledInstr->SetSrc1(src1Opnd);
  670. }
  671. #if DBG
  672. profiledInstr->profileId = Js::Constants::NoProfileId;
  673. profiledInstr->arrayProfileId = Js::Constants::NoProfileId;
  674. profiledInstr->inlineCacheIndex = Js::Constants::NoInlineCacheIndex;
  675. Assert(profiledInstr->loopNumber == 0u - 1);
  676. #endif
  677. // default these to false.
  678. profiledInstr->isProfiledReturnCall = false;
  679. profiledInstr->isBeginSwitch = false;
  680. profiledInstr->isNewArray = false;
  681. profiledInstr->isLoopHelper = false;
  682. return profiledInstr;
  683. }
  684. JitProfilingInstr*
  685. JitProfilingInstr::CloneJitProfiling() const
  686. {
  687. // Adapted from Profiled::CloneProfiledInstr. Note that the dst and srcs are not set.
  688. Assert(!(this->HasBailOutInfo() || this->HasAuxBailOut())); // Shouldn't have bailout info in a jitprofiling instr
  689. return this->CopyJitProfiling();
  690. }
  691. JitProfilingInstr*
  692. JitProfilingInstr::CopyJitProfiling() const
  693. {
  694. // Adapted from Profiled::CopyProfiledInstr. Note that the dst and srcs are not set.
  695. IR::JitProfilingInstr * jitProfInstr;
  696. jitProfInstr = JitAnew(this->m_func->m_alloc, IR::JitProfilingInstr);
  697. jitProfInstr->Init(this->m_opcode, InstrKindProfiled, this->m_func);
  698. jitProfInstr->isProfiledReturnCall = this->isProfiledReturnCall;
  699. jitProfInstr->isBeginSwitch = this->isBeginSwitch;
  700. jitProfInstr->isNewArray = this->isNewArray;
  701. jitProfInstr->isLoopHelper = this->isLoopHelper;
  702. jitProfInstr->profileId = this->profileId;
  703. jitProfInstr->arrayProfileId = this->arrayProfileId;
  704. jitProfInstr->inlineCacheIndex = this->inlineCacheIndex;
  705. Assert(jitProfInstr->loopNumber == this->loopNumber);
  706. return jitProfInstr;
  707. }
  708. ProfiledInstr *
  709. ProfiledInstr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Opnd *src2Opnd, Func * func)
  710. {
  711. ProfiledInstr * profiledInstr = ProfiledInstr::New(opcode, dstOpnd, src1Opnd, func);
  712. profiledInstr->SetSrc2(src2Opnd);
  713. return profiledInstr;
  714. }
  715. ProfiledInstr *
  716. ProfiledInstr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Func * func)
  717. {
  718. ProfiledInstr * profiledInstr = JitAnew(func->m_alloc, IR::ProfiledInstr);
  719. profiledInstr->Init(opcode, InstrKindProfiled, func);
  720. if (dstOpnd)
  721. {
  722. profiledInstr->SetDst(dstOpnd);
  723. }
  724. if (src1Opnd)
  725. {
  726. profiledInstr->SetSrc1(src1Opnd);
  727. }
  728. profiledInstr->u.ldElemInfo = nullptr;
  729. return profiledInstr;
  730. }
  731. ProfiledInstr *
  732. ProfiledInstr::CloneProfiledInstr() const
  733. {
  734. IR::ProfiledInstr * profiledInstr;
  735. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  736. {
  737. profiledInstr = ((ProfiledBailOutInstr *)this)->CloneBailOut();
  738. profiledInstr->u = this->u;
  739. }
  740. else
  741. {
  742. profiledInstr = this->CopyProfiledInstr();
  743. }
  744. return profiledInstr;
  745. }
  746. ProfiledInstr *
  747. ProfiledInstr::CopyProfiledInstr() const
  748. {
  749. IR::ProfiledInstr * profiledInstr;
  750. profiledInstr = JitAnew(this->m_func->m_alloc, IR::ProfiledInstr);
  751. profiledInstr->Init(this->m_opcode, InstrKindProfiled, this->m_func);
  752. profiledInstr->u = this->u;
  753. return profiledInstr;
  754. }
  755. ByteCodeUsesInstr *
  756. ByteCodeUsesInstr::New(IR::Instr * originalBytecodeInstr)
  757. {
  758. Func* func = originalBytecodeInstr->m_func;
  759. ByteCodeUsesInstr * byteCodeUses = JitAnew(func->m_alloc, IR::ByteCodeUsesInstr);
  760. byteCodeUses->Init(Js::OpCode::ByteCodeUses, InstrKindByteCodeUses, func);
  761. byteCodeUses->byteCodeUpwardExposedUsed = nullptr;
  762. byteCodeUses->propertySymUse = nullptr;
  763. byteCodeUses->SetByteCodeOffset(originalBytecodeInstr);
  764. return byteCodeUses;
  765. }
  766. ByteCodeUsesInstr *
  767. ByteCodeUsesInstr::New(Func * func, uint32 offset)
  768. {
  769. ByteCodeUsesInstr * byteCodeUses = JitAnew(func->m_alloc, IR::ByteCodeUsesInstr);
  770. byteCodeUses->Init(Js::OpCode::ByteCodeUses, InstrKindByteCodeUses, func);
  771. byteCodeUses->byteCodeUpwardExposedUsed = nullptr;
  772. byteCodeUses->propertySymUse = nullptr;
  773. byteCodeUses->SetByteCodeOffset(offset);
  774. return byteCodeUses;
  775. }
  776. const BVSparse<JitArenaAllocator> * ByteCodeUsesInstr::GetByteCodeUpwardExposedUsed() const
  777. {
  778. return this->byteCodeUpwardExposedUsed;
  779. }
  780. // In the case of instances where you would like to add a ByteCodeUses to some sym,
  781. // which doesn't have an operand associated with it (like a block closure sym), use
  782. // this to set it without needing to pass the check for JIT-Optimized registers.
  783. void ByteCodeUsesInstr::SetNonOpndSymbol(uint symId)
  784. {
  785. if (!this->byteCodeUpwardExposedUsed)
  786. {
  787. this->byteCodeUpwardExposedUsed = JitAnew(m_func->m_alloc, BVSparse<JitArenaAllocator>, m_func->m_alloc);
  788. }
  789. this->byteCodeUpwardExposedUsed->Set(symId);
  790. }
  791. // In cases where the operand you're working on may be changed between when you get
  792. // access to it and when you determine that you can set it in the ByteCodeUsesInstr
  793. // set method, cache the values and use this caller.
  794. void ByteCodeUsesInstr::SetRemovedOpndSymbol(bool isJITOptimizedReg, uint symId)
  795. {
  796. if (isJITOptimizedReg)
  797. {
  798. AssertMsg(false, "Tried to add a jit-optimized register to a ByteCodeUses instruction!");
  799. // Although we assert on debug builds, we should actually be ok with release builds
  800. // if we ignore the operand; not ignoring it, however, can cause us to introduce an
  801. // inconsistency in bytecode register lifetimes.
  802. return;
  803. }
  804. if(!this->byteCodeUpwardExposedUsed)
  805. {
  806. this->byteCodeUpwardExposedUsed = JitAnew(m_func->m_alloc, BVSparse<JitArenaAllocator>, m_func->m_alloc);
  807. }
  808. this->byteCodeUpwardExposedUsed->Set(symId);
  809. }
  810. void ByteCodeUsesInstr::Set(IR::Opnd * originalOperand)
  811. {
  812. Assert(originalOperand && originalOperand->GetStackSym());
  813. bool isJITOptimizedReg = originalOperand->GetIsJITOptimizedReg();
  814. SymID symId = originalOperand->GetStackSym()->m_id;
  815. if (isJITOptimizedReg)
  816. {
  817. AssertMsg(false, "Tried to add a jit-optimized register to a ByteCodeUses instruction!");
  818. // Although we assert on debug builds, we should actually be ok with release builds
  819. // if we ignore the operand; not ignoring it, however, can cause us to introduce an
  820. // inconsistency in bytecode register lifetimes.
  821. return;
  822. }
  823. if (!this->byteCodeUpwardExposedUsed)
  824. {
  825. this->byteCodeUpwardExposedUsed = JitAnew(m_func->m_alloc, BVSparse<JitArenaAllocator>, m_func->m_alloc);
  826. }
  827. this->byteCodeUpwardExposedUsed->Set(symId);
  828. }
  829. void ByteCodeUsesInstr::Clear(uint symId)
  830. {
  831. Assert(byteCodeUpwardExposedUsed != nullptr);
  832. this->byteCodeUpwardExposedUsed->Clear(symId);
  833. }
  834. void ByteCodeUsesInstr::SetBV(BVSparse<JitArenaAllocator>* newbv)
  835. {
  836. Assert(byteCodeUpwardExposedUsed == nullptr && newbv != nullptr);
  837. byteCodeUpwardExposedUsed = newbv;
  838. }
  839. // If possible, we want to aggregate with subsequent ByteCodeUses Instructions, so
  840. // that we can do some optimizations in other places where we can simplify args in
  841. // a compare, but still need to generate them for bailouts. Without this, we cause
  842. // problems because we end up with an instruction losing atomicity in terms of its
  843. // bytecode use and generation lifetimes.
  844. void ByteCodeUsesInstr::Aggregate()
  845. {
  846. IR::Instr* scanner = this->m_next;
  847. while (scanner && scanner->m_opcode == Js::OpCode::ByteCodeUses && scanner->GetByteCodeOffset() == this->GetByteCodeOffset() && scanner->GetDst() == nullptr)
  848. {
  849. IR::ByteCodeUsesInstr* target = scanner->AsByteCodeUsesInstr();
  850. Assert(this->m_func == target->m_func);
  851. if (target->byteCodeUpwardExposedUsed)
  852. {
  853. if (this->byteCodeUpwardExposedUsed)
  854. {
  855. this->byteCodeUpwardExposedUsed->Or(target->byteCodeUpwardExposedUsed);
  856. JitAdelete(target->byteCodeUpwardExposedUsed->GetAllocator(), target->byteCodeUpwardExposedUsed);
  857. target->byteCodeUpwardExposedUsed = nullptr;
  858. }
  859. else
  860. {
  861. this->byteCodeUpwardExposedUsed = target->byteCodeUpwardExposedUsed;
  862. target->byteCodeUpwardExposedUsed = nullptr;
  863. }
  864. }
  865. scanner = scanner->m_next;
  866. }
  867. }
  868. BailOutInfo *
  869. Instr::GetBailOutInfo() const
  870. {
  871. Assert(this->HasBailOutInfo() || this->HasAuxBailOut());
  872. switch (this->m_kind)
  873. {
  874. case InstrKindInstr:
  875. return ((BailOutInstr const *)this)->bailOutInfo;
  876. case InstrKindProfiled:
  877. return ((ProfiledBailOutInstr const *)this)->bailOutInfo;
  878. case InstrKindBranch:
  879. return ((BranchBailOutInstr const *)this)->bailOutInfo;
  880. default:
  881. Assert(false);
  882. __assume(false);
  883. }
  884. }
  885. BailOutKind
  886. Instr::GetBailOutKind() const
  887. {
  888. Assert(this->HasBailOutInfo());
  889. switch (this->m_kind)
  890. {
  891. case InstrKindInstr:
  892. return ((BailOutInstr const *)this)->bailOutKind;
  893. case InstrKindProfiled:
  894. return ((ProfiledBailOutInstr const *)this)->bailOutKind;
  895. case InstrKindBranch:
  896. return ((BranchBailOutInstr const *)this)->bailOutKind;
  897. default:
  898. Assert(false);
  899. return BailOutInvalid;
  900. }
  901. }
  902. BailOutKind
  903. Instr::GetBailOutKindNoBits() const
  904. {
  905. return GetBailOutKind() & ~IR::BailOutKindBits;
  906. }
  907. BailOutKind
  908. Instr::GetAuxBailOutKind() const
  909. {
  910. Assert(this->HasAuxBailOut());
  911. switch (this->m_kind)
  912. {
  913. case InstrKindInstr:
  914. return ((BailOutInstr const *)this)->auxBailOutKind;
  915. case InstrKindProfiled:
  916. return ((ProfiledBailOutInstr const *)this)->auxBailOutKind;
  917. case InstrKindBranch:
  918. return ((BranchBailOutInstr const *)this)->auxBailOutKind;
  919. default:
  920. Assert(false);
  921. return BailOutInvalid;
  922. }
  923. }
  924. void Instr::SetBailOutKind(const IR::BailOutKind bailOutKind)
  925. {
  926. Assert(this->HasBailOutInfo());
  927. Assert(bailOutKind != IR::BailOutInvalid);
  928. this->SetBailOutKind_NoAssert(bailOutKind);
  929. }
  930. // Helper to set bail out kind, doesn't assert.
  931. void Instr::SetBailOutKind_NoAssert(const IR::BailOutKind bailOutKind)
  932. {
  933. Assert(IsValidBailOutKindAndBits(bailOutKind));
  934. switch (this->m_kind)
  935. {
  936. case InstrKindInstr:
  937. ((BailOutInstr *)this)->bailOutKind = bailOutKind;
  938. break;
  939. case InstrKindProfiled:
  940. ((ProfiledBailOutInstr *)this)->bailOutKind = bailOutKind;
  941. break;
  942. case InstrKindBranch:
  943. ((BranchBailOutInstr *)this)->bailOutKind = bailOutKind;
  944. break;
  945. default:
  946. Assert(false);
  947. __assume(false);
  948. }
  949. }
  950. void Instr::SetAuxBailOutKind(const IR::BailOutKind bailOutKind)
  951. {
  952. switch (this->m_kind)
  953. {
  954. case InstrKindInstr:
  955. ((BailOutInstr *)this)->auxBailOutKind = bailOutKind;
  956. break;
  957. case InstrKindProfiled:
  958. ((ProfiledBailOutInstr *)this)->auxBailOutKind = bailOutKind;
  959. break;
  960. case InstrKindBranch:
  961. ((BranchBailOutInstr *)this)->auxBailOutKind = bailOutKind;
  962. break;
  963. default:
  964. Assert(false);
  965. __assume(false);
  966. }
  967. }
  968. BailOutInfo *
  969. Instr::UnlinkBailOutInfo()
  970. {
  971. BailOutInfo *bailOutInfo;
  972. Assert(this->HasBailOutInfo() || this->HasAuxBailOut());
  973. switch (this->m_kind)
  974. {
  975. case InstrKindInstr:
  976. bailOutInfo = ((BailOutInstr const *)this)->bailOutInfo;
  977. ((BailOutInstr *)this)->bailOutInfo = nullptr;
  978. break;
  979. case InstrKindProfiled:
  980. bailOutInfo = ((ProfiledBailOutInstr const *)this)->bailOutInfo;
  981. ((ProfiledBailOutInstr *)this)->bailOutInfo = nullptr;
  982. break;
  983. case InstrKindBranch:
  984. bailOutInfo = ((BranchBailOutInstr const *)this)->bailOutInfo;
  985. ((BranchBailOutInstr *)this)->bailOutInfo = nullptr;
  986. break;
  987. default:
  988. Assert(false);
  989. return nullptr;
  990. }
  991. Assert(bailOutInfo);
  992. #if 0
  993. if (bailOutInfo->bailOutInstr == this)
  994. {
  995. bailOutInfo->bailOutInstr = nullptr;
  996. }
  997. #endif
  998. this->hasBailOutInfo = false;
  999. this->hasAuxBailOut = false;
  1000. return bailOutInfo;
  1001. }
  1002. bool
  1003. Instr::ReplaceBailOutInfo(BailOutInfo *newBailOutInfo)
  1004. {
  1005. BailOutInfo *oldBailOutInfo;
  1006. bool deleteOld = false;
  1007. #if DBG
  1008. newBailOutInfo->wasCopied = true;
  1009. #endif
  1010. Assert(this->HasBailOutInfo() || this->HasAuxBailOut());
  1011. switch (this->m_kind)
  1012. {
  1013. case InstrKindInstr:
  1014. oldBailOutInfo = ((BailOutInstr *)this)->bailOutInfo;
  1015. ((BailOutInstr *)this)->bailOutInfo = newBailOutInfo;
  1016. break;
  1017. case InstrKindProfiled:
  1018. oldBailOutInfo = ((ProfiledBailOutInstr *)this)->bailOutInfo;
  1019. ((ProfiledBailOutInstr *)this)->bailOutInfo = newBailOutInfo;
  1020. break;
  1021. case InstrKindBranch:
  1022. AssertMsg(!this->HasBailOutInfo() && this->HasAuxBailOut(), "ReplaceBailOutInfo is not used with InstrKindBranch for non-aux bailout");
  1023. oldBailOutInfo = ((BranchBailOutInstr *)this)->bailOutInfo;
  1024. ((BranchBailOutInstr *)this)->bailOutInfo = newBailOutInfo;
  1025. break;
  1026. default:
  1027. Assert(false);
  1028. __assume(UNREACHED);
  1029. }
  1030. Assert(!oldBailOutInfo->wasCloned && !oldBailOutInfo->wasCopied);
  1031. if (oldBailOutInfo->bailOutInstr == this)
  1032. {
  1033. JitArenaAllocator * alloc = this->m_func->m_alloc;
  1034. oldBailOutInfo->Clear(alloc);
  1035. JitAdelete(alloc, oldBailOutInfo);
  1036. deleteOld = true;
  1037. }
  1038. return deleteOld;
  1039. }
  1040. IR::Instr *Instr::ShareBailOut()
  1041. {
  1042. BailOutInfo *const bailOutInfo = GetBailOutInfo();
  1043. bailOutInfo->bailOutInstr = nullptr;
  1044. #if DBG
  1045. bailOutInfo->wasCopied = true;
  1046. #endif
  1047. IR::Instr *const sharedBail =
  1048. IR::BailOutInstr::New(Js::OpCode::BailTarget, IR::BailOutShared, bailOutInfo, bailOutInfo->bailOutFunc);
  1049. sharedBail->SetByteCodeOffset(this);
  1050. InsertAfter(sharedBail);
  1051. Assert(bailOutInfo->bailOutInstr == sharedBail);
  1052. return sharedBail;
  1053. }
  1054. void
  1055. Instr::UnlinkStartCallFromBailOutInfo(IR::Instr *endInstr) const
  1056. {
  1057. #ifdef _M_IX86
  1058. // The StartCall instruction is being deleted, or is being moved and may later be deleted,
  1059. // so remove its references from bailouts in the given range.
  1060. // This only happens during cloning, which is rare, and only across the range of instructions
  1061. // that evaluate outgoing arguments, which is long only in synthetic cases.
  1062. Assert(this->m_opcode == Js::OpCode::StartCall);
  1063. if (!this->m_func->hasBailout)
  1064. {
  1065. return;
  1066. }
  1067. FOREACH_INSTR_IN_RANGE(instr, this->m_next, endInstr)
  1068. {
  1069. if (instr->HasBailOutInfo())
  1070. {
  1071. BailOutInfo *bailOutInfo = instr->GetBailOutInfo();
  1072. bailOutInfo->UnlinkStartCall(this);
  1073. }
  1074. }
  1075. NEXT_INSTR_IN_RANGE;
  1076. #endif
  1077. }
  1078. Opnd *Instr::FindCallArgumentOpnd(const Js::ArgSlot argSlot, IR::Instr * *const ownerInstrRef)
  1079. {
  1080. Assert(OpCodeAttr::CallInstr(m_opcode));
  1081. Assert(argSlot != static_cast<Js::ArgSlot>(0));
  1082. IR::Instr *argInstr = this;
  1083. Assert(argInstr->GetSrc2());
  1084. Assert(argInstr->GetSrc2()->IsSymOpnd());
  1085. do
  1086. {
  1087. StackSym *const linkSym = argInstr->GetSrc2()->AsSymOpnd()->m_sym->AsStackSym();
  1088. Assert(linkSym->IsSingleDef());
  1089. Assert(linkSym->IsArgSlotSym());
  1090. argInstr = linkSym->m_instrDef;
  1091. Assert(argInstr->GetSrc2());
  1092. if(argInstr->m_opcode == Js::OpCode::ArgOut_A_InlineSpecialized)
  1093. {
  1094. // This is a fake ArgOut, skip it
  1095. continue;
  1096. }
  1097. if(linkSym->GetArgSlotNum() == argSlot)
  1098. {
  1099. if(ownerInstrRef)
  1100. {
  1101. *ownerInstrRef = argInstr;
  1102. }
  1103. return argInstr->GetSrc1();
  1104. }
  1105. } while(argInstr->GetSrc2()->IsSymOpnd());
  1106. return nullptr;
  1107. }
  1108. bool
  1109. Instr::FetchOperands(_Out_writes_(argsOpndLength) IR::Opnd **argsOpnd, uint argsOpndLength)
  1110. {
  1111. return this->ForEachCallDirectArgOutInstrBackward([&](IR::Instr *argOutInstr, uint argNum)
  1112. {
  1113. argsOpnd[argNum] = argOutInstr->GetSrc1();
  1114. return argNum == 0;
  1115. }, argsOpndLength);
  1116. }
  1117. bool Instr::ShouldCheckForNegativeZero() const
  1118. {
  1119. return !ignoreNegativeZero;
  1120. }
  1121. bool Instr::IsDstNotAlwaysConvertedToInt32() const
  1122. {
  1123. return !dstIsAlwaysConvertedToInt32;
  1124. }
  1125. bool Instr::IsDstNotAlwaysConvertedToNumber() const
  1126. {
  1127. return !dstIsAlwaysConvertedToNumber;
  1128. }
  1129. bool Instr::ShouldCheckForIntOverflow() const
  1130. {
  1131. return ShouldCheckFor32BitOverflow() || ShouldCheckForNon32BitOverflow();
  1132. }
  1133. bool Instr::ShouldCheckFor32BitOverflow() const
  1134. {
  1135. return !(ignoreIntOverflow || ignoreIntOverflowInRange);
  1136. }
  1137. bool Instr::ShouldCheckForNon32BitOverflow() const
  1138. {
  1139. return ignoreOverflowBitCount != 32;
  1140. }
  1141. template <typename InstrType> struct IRKindMap;
  1142. template <> struct IRKindMap<IR::Instr> { static const IRKind InstrKind = InstrKindInstr; };
  1143. template <> struct IRKindMap<IR::ProfiledInstr> { static const IRKind InstrKind = InstrKindProfiled; };
  1144. template <> struct IRKindMap<IR::BranchInstr> { static const IRKind InstrKind = InstrKindBranch; };
  1145. template <typename InstrType>
  1146. BailOutInstrTemplate<InstrType> *
  1147. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1148. {
  1149. Assert(func == bailOutTarget->m_func);
  1150. BailOutInfo * bailOutInfo = JitAnew(func->m_alloc, BailOutInfo, bailOutTarget->GetByteCodeOffset(), func);
  1151. #if ENABLE_DEBUG_CONFIG_OPTIONS
  1152. bailOutInfo->bailOutOpcode = opcode;
  1153. #endif
  1154. return BailOutInstrTemplate::New(opcode, kind, bailOutInfo, func);
  1155. }
  1156. template <typename InstrType>
  1157. BailOutInstrTemplate<InstrType> *
  1158. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, IR::Opnd *dst, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1159. {
  1160. BailOutInstrTemplate *instr = BailOutInstrTemplate::New(opcode, kind, bailOutTarget, func);
  1161. instr->SetDst(dst);
  1162. return instr;
  1163. }
  1164. template <typename InstrType>
  1165. BailOutInstrTemplate<InstrType> *
  1166. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, IR::Opnd *dst, IR::Opnd *src1, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1167. {
  1168. BailOutInstrTemplate *instr = BailOutInstrTemplate::New(opcode, dst, kind, bailOutTarget, func);
  1169. instr->SetSrc1(src1);
  1170. return instr;
  1171. }
  1172. template <typename InstrType>
  1173. BailOutInstrTemplate<InstrType> *
  1174. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, IR::Opnd *dst, IR::Opnd *src1, IR::Opnd *src2, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1175. {
  1176. BailOutInstrTemplate *instr = BailOutInstrTemplate::New(opcode, dst, src1, kind, bailOutTarget, func);
  1177. instr->SetSrc2(src2);
  1178. return instr;
  1179. }
  1180. template <typename InstrType>
  1181. BailOutInstrTemplate<InstrType> *
  1182. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, BailOutKind kind, BailOutInfo * bailOutInfo, Func * func)
  1183. {
  1184. Assert(func == bailOutInfo->bailOutFunc);
  1185. Assert(IsValidBailOutKindAndBits(kind));
  1186. BailOutInstrTemplate * bailOutInstr = JitAnew(func->m_alloc, BailOutInstrTemplate);
  1187. bailOutInstr->Init(opcode, IRKindMap<InstrType>::InstrKind, func);
  1188. #if ENABLE_DEBUG_CONFIG_OPTIONS
  1189. bailOutInfo->bailOutOpcode = opcode;
  1190. #endif
  1191. bailOutInstr->bailOutInfo = bailOutInfo;
  1192. bailOutInstr->bailOutKind = kind;
  1193. bailOutInstr->auxBailOutKind = BailOutInvalid;
  1194. if (bailOutInfo->bailOutInstr == nullptr)
  1195. {
  1196. bailOutInfo->bailOutInstr = bailOutInstr;
  1197. }
  1198. else if (bailOutInfo->sharedBailOutKind)
  1199. {
  1200. if (bailOutInfo->bailOutInstr->HasBailOutInfo())
  1201. {
  1202. bailOutInfo->sharedBailOutKind = bailOutInfo->bailOutInstr->GetBailOutKind() == kind;
  1203. }
  1204. else
  1205. {
  1206. // Rare cases where we have already generated the bailout record. Unlikely they share the same bailout kind as this is hit only when we try to
  1207. // share bailout in lowerer. See Instr::ShareBailOut.
  1208. bailOutInfo->sharedBailOutKind = false;
  1209. }
  1210. }
  1211. func->hasBailout = true;
  1212. // Indicate that the function has bailout instructions
  1213. // This information is used to determine whether to free jitted loop bodies
  1214. // If the function has bailout instructions, we keep the loop bodies alive
  1215. // in case we bail out to the interpreter, so that we can reuse the jitted
  1216. // loop bodies
  1217. func->GetJITOutput()->SetHasBailoutInstr(true);
  1218. return bailOutInstr;
  1219. }
  1220. template <typename InstrType>
  1221. BailOutInstrTemplate<InstrType> *
  1222. BailOutInstrTemplate<InstrType>::CloneBailOut() const
  1223. {
  1224. Assert(this->m_func->hasBailout);
  1225. Assert(!this->bailOutInfo->wasCloned);
  1226. BailOutInstrTemplate * bailOutInstr = BailOutInstrTemplate::New(this->m_opcode, this->bailOutKind, this->bailOutInfo, this->bailOutInfo->bailOutFunc);
  1227. bailOutInstr->hasAuxBailOut = this->hasAuxBailOut;
  1228. bailOutInstr->auxBailOutKind = this->auxBailOutKind;
  1229. bailOutInstr->bailOutInfo->wasCloned = true;
  1230. // the new copy is in the slow path and generate the real bailout
  1231. bailOutInstr->bailOutInfo->bailOutInstr = bailOutInstr;
  1232. return bailOutInstr;
  1233. }
  1234. template class BailOutInstrTemplate<IR::Instr>;
  1235. ///----------------------------------------------------------------------------
  1236. ///
  1237. /// EntryInstr::New
  1238. ///
  1239. /// Create an EntryInstr.
  1240. ///
  1241. ///----------------------------------------------------------------------------
  1242. EntryInstr *
  1243. EntryInstr::New(Js::OpCode opcode, Func *func)
  1244. {
  1245. EntryInstr * entryInstr;
  1246. entryInstr = JitAnew(func->m_alloc, IR::EntryInstr);
  1247. entryInstr->Init(opcode, InstrKindEntry, func);
  1248. return entryInstr;
  1249. }
  1250. ///----------------------------------------------------------------------------
  1251. ///
  1252. /// ExitInstr::New
  1253. ///
  1254. /// Create an ExitInstr.
  1255. ///
  1256. ///----------------------------------------------------------------------------
  1257. ExitInstr *
  1258. ExitInstr::New(Js::OpCode opcode, Func *func)
  1259. {
  1260. ExitInstr * exitInstr;
  1261. exitInstr = JitAnew(func->m_alloc, IR::ExitInstr);
  1262. exitInstr->Init(opcode, InstrKindExit, func);
  1263. return exitInstr;
  1264. }
  1265. ///----------------------------------------------------------------------------
  1266. ///
  1267. /// LabelInstr::New
  1268. ///
  1269. /// Create a label.
  1270. ///
  1271. ///----------------------------------------------------------------------------
  1272. LabelInstr *
  1273. LabelInstr::New(Js::OpCode opcode, Func *func, bool isOpHelper)
  1274. {
  1275. LabelInstr * labelInstr;
  1276. labelInstr = JitAnew(func->m_alloc, IR::LabelInstr, func->m_alloc);
  1277. labelInstr->Init(opcode, InstrKindLabel, func, isOpHelper);
  1278. return labelInstr;
  1279. }
  1280. void
  1281. LabelInstr::Init(Js::OpCode opcode, IRKind kind, Func *func, bool isOpHelper)
  1282. {
  1283. // Pass in the region when this is called from anywhere between the Lowerer and EHBailoutPatchUp code?
  1284. __super::Init(opcode, kind, func);
  1285. this->isOpHelper = isOpHelper;
  1286. this->m_pc.pc = nullptr;
  1287. this->m_id = ++(func->GetTopFunc()->m_labelCount);
  1288. AssertMsg(this->m_id != 0, "Label numbers wrapped around?");
  1289. }
  1290. ///----------------------------------------------------------------------------
  1291. ///
  1292. /// LabelInstr::AddLabelRef
  1293. ///
  1294. /// Add a branch to the list of label references.
  1295. ///
  1296. ///----------------------------------------------------------------------------
  1297. void
  1298. LabelInstr::AddLabelRef(BranchInstr *branchRef)
  1299. {
  1300. this->labelRefs.Prepend(branchRef);
  1301. }
  1302. ///----------------------------------------------------------------------------
  1303. ///
  1304. /// LabelInstr::RemoveLabelRef
  1305. ///
  1306. /// Remove a branch from the list of label references.
  1307. ///
  1308. ///----------------------------------------------------------------------------
  1309. void
  1310. LabelInstr::RemoveLabelRef(BranchInstr *branchRef)
  1311. {
  1312. FOREACH_SLISTCOUNTED_ENTRY_EDITING(BranchInstr*, branchEntry, &this->labelRefs, iter)
  1313. {
  1314. if (branchEntry == branchRef)
  1315. {
  1316. iter.RemoveCurrent();
  1317. return;
  1318. }
  1319. } NEXT_SLISTCOUNTED_ENTRY_EDITING;
  1320. AssertMsg(UNREACHED, "Branch not found on labelRef list");
  1321. }
  1322. ///----------------------------------------------------------------------------
  1323. ///
  1324. /// BranchInstr::New
  1325. ///
  1326. /// Create a Br (unconditional) BranchInstr.
  1327. ///
  1328. ///----------------------------------------------------------------------------
  1329. BranchInstr *
  1330. BranchInstr::New(Js::OpCode opcode, LabelInstr * branchTarget, Func *func)
  1331. {
  1332. BranchInstr * branchInstr;
  1333. branchInstr = JitAnew(func->m_alloc, IR::BranchInstr);
  1334. branchInstr->Init(opcode, InstrKindBranch, func);
  1335. branchInstr->SetTarget(branchTarget);
  1336. branchInstr->m_dst = nullptr;
  1337. branchInstr->m_src1 = nullptr;
  1338. branchInstr->m_src2 = nullptr;
  1339. branchInstr->m_byteCodeReg = Js::Constants::NoRegister;
  1340. #if DBG
  1341. branchInstr->m_isHelperToNonHelperBranch = false;
  1342. #endif
  1343. return branchInstr;
  1344. }
  1345. ///----------------------------------------------------------------------------
  1346. ///
  1347. /// BranchInstr::New
  1348. ///
  1349. /// Create a BrB BranchInstr (1-operand conditional branch).
  1350. ///
  1351. ///----------------------------------------------------------------------------
  1352. BranchInstr *
  1353. BranchInstr::New(Js::OpCode opcode, LabelInstr * branchTarget, Opnd *srcOpnd, Func *func)
  1354. {
  1355. BranchInstr * branchInstr;
  1356. branchInstr = BranchInstr::New(opcode, branchTarget, func);
  1357. branchInstr->SetSrc1(srcOpnd);
  1358. return branchInstr;
  1359. }
  1360. ///----------------------------------------------------------------------------
  1361. ///
  1362. /// BranchInstr::New
  1363. ///
  1364. /// Create a BrBReturn BranchInstr (1-operand conditional branch. If condition fails return the result of the condition).
  1365. ///
  1366. ///----------------------------------------------------------------------------
  1367. BranchInstr *
  1368. BranchInstr::New(Js::OpCode opcode, Opnd* destOpnd, LabelInstr * branchTarget, Opnd *srcOpnd, Func *func)
  1369. {
  1370. BranchInstr * branchInstr;
  1371. branchInstr = BranchInstr::New(opcode, branchTarget, func);
  1372. branchInstr->SetSrc1(srcOpnd);
  1373. branchInstr->SetDst(destOpnd);
  1374. return branchInstr;
  1375. }
  1376. ///----------------------------------------------------------------------------
  1377. ///
  1378. /// BranchInstr::New
  1379. ///
  1380. /// Create a BrReg2 BranchInstr (2-operand conditional branch).
  1381. ///
  1382. ///----------------------------------------------------------------------------
  1383. BranchInstr *
  1384. BranchInstr::New(Js::OpCode opcode, LabelInstr * branchTarget, Opnd *src1Opnd, Opnd *src2Opnd, Func *func)
  1385. {
  1386. BranchInstr * branchInstr;
  1387. branchInstr = BranchInstr::New(opcode, branchTarget, src1Opnd, func);
  1388. branchInstr->SetSrc2(src2Opnd);
  1389. return branchInstr;
  1390. }
  1391. ///----------------------------------------------------------------------------
  1392. ///
  1393. /// MultiBranchInstr::New
  1394. ///
  1395. /// Create a MultiBr BranchInstr (unconditional multi branch).
  1396. ///
  1397. ///----------------------------------------------------------------------------
  1398. MultiBranchInstr *
  1399. MultiBranchInstr::New(Js::OpCode opcode, IR::Opnd * srcOpnd, Func * func)
  1400. {
  1401. MultiBranchInstr * multiBranchInstr;
  1402. multiBranchInstr = MultiBranchInstr::New(opcode, func);
  1403. multiBranchInstr->SetSrc1(srcOpnd);
  1404. return multiBranchInstr;
  1405. }
  1406. MultiBranchInstr *
  1407. MultiBranchInstr::New(Js::OpCode opcode, Func * func)
  1408. {
  1409. JitArenaAllocator * m_funcAlloc = func->m_alloc;
  1410. MultiBranchInstr * multiBranchInstr;
  1411. multiBranchInstr = JitAnew(m_funcAlloc, IR::MultiBranchInstr);
  1412. multiBranchInstr->Init(opcode, InstrKindBranch, func);
  1413. return multiBranchInstr;
  1414. }
  1415. bool
  1416. BranchInstr::ReplaceTarget(IR::LabelInstr * oldLabelInstr, IR::LabelInstr * newLabelInstr)
  1417. {
  1418. if (this->IsMultiBranch())
  1419. {
  1420. return this->AsMultiBrInstr()->ReplaceTarget(oldLabelInstr, newLabelInstr);
  1421. }
  1422. if (this->GetTarget() == oldLabelInstr)
  1423. {
  1424. this->SetTarget(newLabelInstr);
  1425. return true;
  1426. }
  1427. return false;
  1428. }
  1429. bool
  1430. MultiBranchInstr::ReplaceTarget(IR::LabelInstr * oldLabelInstr, IR::LabelInstr * newLabelInstr)
  1431. {
  1432. Assert(this->IsMultiBranch());
  1433. bool remapped = false;
  1434. this->UpdateMultiBrLabels([=, &remapped](IR::LabelInstr * targetLabel) -> IR::LabelInstr *
  1435. {
  1436. if (targetLabel == oldLabelInstr)
  1437. {
  1438. this->ChangeLabelRef(targetLabel, newLabelInstr);
  1439. remapped = true;
  1440. return newLabelInstr;
  1441. }
  1442. return targetLabel;
  1443. });
  1444. return remapped;
  1445. }
  1446. void
  1447. MultiBranchInstr::ClearTarget()
  1448. {
  1449. Assert(IsMultiBranch());
  1450. MapMultiBrLabels([&](LabelInstr *const targetLabel)
  1451. {
  1452. ChangeLabelRef(targetLabel, nullptr);
  1453. });
  1454. m_branchTargets = nullptr;
  1455. }
  1456. BranchInstr *
  1457. BranchInstr::CloneBranchInstr() const
  1458. {
  1459. AssertMsg(!this->IsMultiBranch(),"Cloning Not supported for MultiBranchInstr");
  1460. Func * func = this->m_func;
  1461. // See if the target has already been cloned.
  1462. IR::LabelInstr * instrLabel = this->GetTarget()->CloneLabel(false);
  1463. if (instrLabel == nullptr)
  1464. {
  1465. // We didn't find a clone for this label.
  1466. // We'll go back and retarget the cloned branch if the target turns up in the cloned range.
  1467. instrLabel = this->GetTarget();
  1468. func->GetCloner()->fRetargetClonedBranch = TRUE;
  1469. }
  1470. return IR::BranchInstr::New(this->m_opcode, instrLabel, func);
  1471. }
  1472. void
  1473. BranchInstr::Invert()
  1474. {
  1475. /*
  1476. * If one of the operands to a relational operator is 'undefined', the result
  1477. * is always false. Don't invert such branches as they result in a jump to
  1478. * the wrong target.
  1479. */
  1480. switch (this->m_opcode)
  1481. {
  1482. case Js::OpCode::BrGt_A:
  1483. this->m_opcode = Js::OpCode::BrNotGt_A;
  1484. break;
  1485. case Js::OpCode::BrNotGt_A:
  1486. this->m_opcode = Js::OpCode::BrGt_A;
  1487. break;
  1488. case Js::OpCode::BrGe_A:
  1489. this->m_opcode = Js::OpCode::BrNotGe_A;
  1490. break;
  1491. case Js::OpCode::BrNotGe_A:
  1492. this->m_opcode = Js::OpCode::BrGe_A;
  1493. break;
  1494. case Js::OpCode::BrLt_A:
  1495. this->m_opcode = Js::OpCode::BrNotLt_A;
  1496. break;
  1497. case Js::OpCode::BrNotLt_A:
  1498. this->m_opcode = Js::OpCode::BrLt_A;
  1499. break;
  1500. case Js::OpCode::BrLe_A:
  1501. this->m_opcode = Js::OpCode::BrNotLe_A;
  1502. break;
  1503. case Js::OpCode::BrNotLe_A:
  1504. this->m_opcode = Js::OpCode::BrLe_A;
  1505. break;
  1506. case Js::OpCode::BrEq_A:
  1507. this->m_opcode = Js::OpCode::BrNotEq_A;
  1508. break;
  1509. case Js::OpCode::BrNotEq_A:
  1510. this->m_opcode = Js::OpCode::BrEq_A;
  1511. break;
  1512. case Js::OpCode::BrNeq_A:
  1513. this->m_opcode = Js::OpCode::BrNotNeq_A;
  1514. break;
  1515. case Js::OpCode::BrNotNeq_A:
  1516. this->m_opcode = Js::OpCode::BrNeq_A;
  1517. break;
  1518. case Js::OpCode::Br:
  1519. break;
  1520. case Js::OpCode::BrFalse_A:
  1521. this->m_opcode = Js::OpCode::BrTrue_A;
  1522. break;
  1523. case Js::OpCode::BrTrue_A:
  1524. this->m_opcode = Js::OpCode::BrFalse_A;
  1525. break;
  1526. case Js::OpCode::BrSrEq_A:
  1527. this->m_opcode = Js::OpCode::BrSrNotEq_A;
  1528. break;
  1529. case Js::OpCode::BrSrNotEq_A:
  1530. this->m_opcode = Js::OpCode::BrSrEq_A;
  1531. break;
  1532. case Js::OpCode::BrSrNeq_A:
  1533. this->m_opcode = Js::OpCode::BrSrNotNeq_A;
  1534. break;
  1535. case Js::OpCode::BrSrNotNeq_A:
  1536. this->m_opcode = Js::OpCode::BrSrNeq_A;
  1537. break;
  1538. case Js::OpCode::BrOnHasProperty:
  1539. this->m_opcode = Js::OpCode::BrOnNoProperty;
  1540. break;
  1541. case Js::OpCode::BrOnNoProperty:
  1542. this->m_opcode = Js::OpCode::BrOnHasProperty;
  1543. break;
  1544. case Js::OpCode::BrTrue_I4:
  1545. this->m_opcode = Js::OpCode::BrFalse_I4;
  1546. break;
  1547. case Js::OpCode::BrFalse_I4:
  1548. this->m_opcode = Js::OpCode::BrTrue_I4;
  1549. break;
  1550. case Js::OpCode::BrEq_I4:
  1551. this->m_opcode = Js::OpCode::BrNeq_I4;
  1552. break;
  1553. case Js::OpCode::BrNeq_I4:
  1554. this->m_opcode = Js::OpCode::BrEq_I4;
  1555. break;
  1556. case Js::OpCode::BrGe_I4:
  1557. this->m_opcode = Js::OpCode::BrLt_I4;
  1558. break;
  1559. case Js::OpCode::BrGt_I4:
  1560. this->m_opcode = Js::OpCode::BrLe_I4;
  1561. break;
  1562. case Js::OpCode::BrLe_I4:
  1563. this->m_opcode = Js::OpCode::BrGt_I4;
  1564. break;
  1565. case Js::OpCode::BrLt_I4:
  1566. this->m_opcode = Js::OpCode::BrGe_I4;
  1567. break;
  1568. case Js::OpCode::BrUnGe_A:
  1569. this->m_opcode = Js::OpCode::BrUnLt_A;
  1570. break;
  1571. case Js::OpCode::BrUnGt_A:
  1572. this->m_opcode = Js::OpCode::BrUnLe_A;
  1573. break;
  1574. case Js::OpCode::BrUnLe_A:
  1575. this->m_opcode = Js::OpCode::BrUnGt_A;
  1576. break;
  1577. case Js::OpCode::BrUnLt_A:
  1578. this->m_opcode = Js::OpCode::BrUnGe_A;
  1579. break;
  1580. case Js::OpCode::BrUnGe_I4:
  1581. this->m_opcode = Js::OpCode::BrUnLt_I4;
  1582. break;
  1583. case Js::OpCode::BrUnGt_I4:
  1584. this->m_opcode = Js::OpCode::BrUnLe_I4;
  1585. break;
  1586. case Js::OpCode::BrUnLe_I4:
  1587. this->m_opcode = Js::OpCode::BrUnGt_I4;
  1588. break;
  1589. case Js::OpCode::BrUnLt_I4:
  1590. this->m_opcode = Js::OpCode::BrUnGe_I4;
  1591. break;
  1592. case Js::OpCode::BrOnEmpty:
  1593. this->m_opcode = Js::OpCode::BrOnNotEmpty;
  1594. break;
  1595. case Js::OpCode::BrOnNotEmpty:
  1596. this->m_opcode = Js::OpCode::BrOnEmpty;
  1597. break;
  1598. case Js::OpCode::BrHasSideEffects:
  1599. this->m_opcode = Js::OpCode::BrNotHasSideEffects;
  1600. break;
  1601. case Js::OpCode::BrFncEqApply:
  1602. this->m_opcode = Js::OpCode::BrFncNeqApply;
  1603. break;
  1604. case Js::OpCode::BrFncNeqApply:
  1605. this->m_opcode = Js::OpCode::BrFncEqApply;
  1606. break;
  1607. case Js::OpCode::BrNotHasSideEffects:
  1608. this->m_opcode = Js::OpCode::BrHasSideEffects;
  1609. break;
  1610. case Js::OpCode::BrNotAddr_A:
  1611. this->m_opcode = Js::OpCode::BrAddr_A;
  1612. break;
  1613. case Js::OpCode::BrAddr_A:
  1614. this->m_opcode = Js::OpCode::BrNotAddr_A;
  1615. break;
  1616. case Js::OpCode::BrFncCachedScopeEq:
  1617. this->m_opcode = Js::OpCode::BrFncCachedScopeNeq;
  1618. break;
  1619. case Js::OpCode::BrFncCachedScopeNeq:
  1620. this->m_opcode = Js::OpCode::BrFncCachedScopeEq;
  1621. break;
  1622. case Js::OpCode::BrOnException:
  1623. this->m_opcode = Js::OpCode::BrOnNoException;
  1624. break;
  1625. default:
  1626. AssertMsg(UNREACHED, "Unhandled branch");
  1627. }
  1628. }
  1629. bool
  1630. BranchInstr::IsLoopTail(Func * func)
  1631. {
  1632. Assert(func->isPostLower);
  1633. IR::LabelInstr * target = this->GetTarget();
  1634. if (!target->m_isLoopTop)
  1635. {
  1636. return false;
  1637. }
  1638. IR::BranchInstr * lastBranchInstr = nullptr;
  1639. uint32 lastBranchNum = 0;
  1640. FOREACH_SLISTCOUNTED_ENTRY(IR::BranchInstr *, ref, &target->labelRefs)
  1641. {
  1642. if (ref->GetNumber() > lastBranchNum)
  1643. {
  1644. lastBranchInstr = ref;
  1645. lastBranchNum = lastBranchInstr->GetNumber();
  1646. }
  1647. }
  1648. NEXT_SLISTCOUNTED_ENTRY;
  1649. if (this == lastBranchInstr)
  1650. {
  1651. return true;
  1652. }
  1653. return false;
  1654. }
  1655. ///----------------------------------------------------------------------------
  1656. ///
  1657. /// PragmaInstr::New
  1658. ///
  1659. /// Create a PragmaInstr.
  1660. ///
  1661. ///----------------------------------------------------------------------------
  1662. PragmaInstr *
  1663. PragmaInstr::New(Js::OpCode opcode, uint32 index, Func *func)
  1664. {
  1665. PragmaInstr * pragmaInstr;
  1666. pragmaInstr = JitAnew(func->m_alloc, IR::PragmaInstr);
  1667. pragmaInstr->Init(opcode, InstrKindPragma, func);
  1668. pragmaInstr->m_statementIndex = index;
  1669. return pragmaInstr;
  1670. }
  1671. ///----------------------------------------------------------------------------
  1672. ///
  1673. /// PragmaInstr::Instr
  1674. ///
  1675. /// Record the information encoded in the pragma
  1676. ///
  1677. ///----------------------------------------------------------------------------
  1678. #if DBG_DUMP | defined(VTUNE_PROFILING)
  1679. void
  1680. PragmaInstr::Record(uint32 nativeBufferOffset)
  1681. {
  1682. // Currently the only pragma instructions are for Source Info
  1683. Assert(this->m_func->GetTopFunc()->DoRecordNativeMap());
  1684. if (!m_func->IsOOPJIT())
  1685. {
  1686. m_func->GetTopFunc()->GetInProcJITEntryPointInfo()->RecordNativeMap(nativeBufferOffset, m_statementIndex);
  1687. }
  1688. }
  1689. #endif
  1690. ///----------------------------------------------------------------------------
  1691. ///
  1692. /// Instr::New
  1693. ///
  1694. /// Create an Instr.
  1695. ///
  1696. ///----------------------------------------------------------------------------
  1697. Instr *
  1698. Instr::New(Js::OpCode opcode, Func *func)
  1699. {
  1700. Instr * instr;
  1701. instr = JitAnew(func->m_alloc, IR::Instr);
  1702. instr->Init(opcode, InstrKindInstr, func);
  1703. return instr;
  1704. }
  1705. ///----------------------------------------------------------------------------
  1706. ///
  1707. /// Instr::New
  1708. ///
  1709. /// Create an Instr with dst.
  1710. ///
  1711. ///----------------------------------------------------------------------------
  1712. Instr *
  1713. Instr::New(Js::OpCode opcode, Opnd *dstOpnd, Func *func)
  1714. {
  1715. Instr * instr;
  1716. instr = Instr::New(opcode, func);
  1717. instr->SetDst(dstOpnd);
  1718. return instr;
  1719. }
  1720. ///----------------------------------------------------------------------------
  1721. ///
  1722. /// Instr::New
  1723. ///
  1724. /// Create an Instr with dst and a src.
  1725. ///
  1726. ///----------------------------------------------------------------------------
  1727. Instr *
  1728. Instr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Func *func)
  1729. {
  1730. Instr * instr;
  1731. instr = Instr::New(opcode, dstOpnd, func);
  1732. instr->SetSrc1(src1Opnd);
  1733. return instr;
  1734. }
  1735. ///----------------------------------------------------------------------------
  1736. ///
  1737. /// Instr::New
  1738. ///
  1739. /// Create an Instr with dst and 2 srcs.
  1740. ///
  1741. ///----------------------------------------------------------------------------
  1742. Instr *
  1743. Instr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Opnd *src2Opnd, Func *func)
  1744. {
  1745. Instr * instr;
  1746. instr = Instr::New(opcode, dstOpnd, src1Opnd, func);
  1747. instr->SetSrc2(src2Opnd);
  1748. return instr;
  1749. }
  1750. ///----------------------------------------------------------------------------
  1751. ///
  1752. /// Instr::SetDst
  1753. ///
  1754. /// Set the dst for 'this' instruction. Automatically maintain isSingleDef
  1755. /// and instrDef of stackSyms.
  1756. ///
  1757. ///----------------------------------------------------------------------------
  1758. Opnd *
  1759. Instr::SetDst(Opnd * newDst)
  1760. {
  1761. AssertMsg(newDst != nullptr, "Calling SetDst with a NULL dst");
  1762. AssertMsg(this->m_dst == nullptr, "Calling SetDst without unlinking/freeing the current dst");
  1763. Assert(!(newDst->IsRegOpnd() && newDst->AsRegOpnd()->IsSymValueFrozen()));
  1764. newDst = newDst->Use(m_func);
  1765. this->m_dst = newDst;
  1766. // If newDst isSingleDef, set instrDef
  1767. StackSym *stackSym;
  1768. if (newDst->IsRegOpnd() && newDst->AsRegOpnd()->m_sym)
  1769. {
  1770. stackSym = newDst->AsRegOpnd()->m_sym->AsStackSym();
  1771. }
  1772. else if (newDst->IsSymOpnd() && newDst->AsSymOpnd()->m_sym->IsStackSym())
  1773. {
  1774. stackSym = newDst->AsSymOpnd()->m_sym->AsStackSym();
  1775. }
  1776. else
  1777. {
  1778. stackSym = nullptr;
  1779. }
  1780. if (stackSym && stackSym->m_isSingleDef)
  1781. {
  1782. if (stackSym->m_instrDef)
  1783. {
  1784. AssertMsg(!stackSym->IsArgSlotSym(), "Arg Slot sym needs to be single def to maintain the StartCall arg links");
  1785. // Multiple defs, clear isSingleDef flag
  1786. stackSym->m_isSingleDef = false;
  1787. stackSym->m_instrDef = nullptr;
  1788. stackSym->m_isConst = false;
  1789. stackSym->m_isIntConst = false;
  1790. stackSym->m_isInt64Const= false;
  1791. stackSym->m_isTaggableIntConst = false;
  1792. stackSym->m_isNotInt = false;
  1793. stackSym->m_isStrConst = false;
  1794. stackSym->m_isStrEmpty = false;
  1795. stackSym->m_isFltConst = false;
  1796. }
  1797. else
  1798. {
  1799. stackSym->m_instrDef = this;
  1800. }
  1801. }
  1802. return newDst;
  1803. }
  1804. Opnd *
  1805. Instr::SetFakeDst(Opnd * newDst)
  1806. {
  1807. AssertMsg(newDst != nullptr, "Calling SetDst with a NULL dst");
  1808. AssertMsg(this->m_dst == nullptr, "Calling SetDst without unlinking/freeing the current dst");
  1809. Assert(!(newDst->IsRegOpnd() && newDst->AsRegOpnd()->IsSymValueFrozen()));
  1810. newDst = newDst->Use(m_func);
  1811. this->m_dst = newDst;
  1812. #if DBG
  1813. newDst->isFakeDst = true;
  1814. #endif
  1815. return newDst;
  1816. }
  1817. ///----------------------------------------------------------------------------
  1818. ///
  1819. /// Instr::UnlinkDst
  1820. ///
  1821. /// Unlinks the dst for 'this' instruction. Automatically maintains
  1822. /// instrDef of stackSyms.
  1823. ///
  1824. ///----------------------------------------------------------------------------
  1825. Opnd *
  1826. Instr::UnlinkDst()
  1827. {
  1828. Opnd * oldDst = this->m_dst;
  1829. StackSym *stackSym = nullptr;
  1830. // If oldDst isSingleDef, clear instrDef
  1831. if (oldDst->IsRegOpnd())
  1832. {
  1833. stackSym = oldDst->AsRegOpnd()->m_sym;
  1834. }
  1835. else if (oldDst->IsSymOpnd())
  1836. {
  1837. Sym *sym = oldDst->AsSymOpnd()->m_sym;
  1838. if (sym->IsStackSym())
  1839. {
  1840. stackSym = sym->AsStackSym();
  1841. }
  1842. }
  1843. #if DBG
  1844. if (oldDst->isFakeDst)
  1845. {
  1846. oldDst->isFakeDst = false;
  1847. }
  1848. #endif
  1849. if (stackSym && stackSym->m_isSingleDef)
  1850. {
  1851. AssertMsg(stackSym->m_instrDef == this, "m_instrDef incorrectly set");
  1852. stackSym->m_instrDef = nullptr;
  1853. }
  1854. oldDst->UnUse();
  1855. this->m_dst = nullptr;
  1856. return oldDst;
  1857. }
  1858. ///----------------------------------------------------------------------------
  1859. ///
  1860. /// Instr::FreeDst
  1861. ///
  1862. /// Unlinks and free the dst for 'this' instruction.
  1863. ///
  1864. ///----------------------------------------------------------------------------
  1865. void
  1866. Instr::FreeDst()
  1867. {
  1868. Opnd * unlinkedDst;
  1869. unlinkedDst = this->UnlinkDst();
  1870. unlinkedDst->Free(this->m_func);
  1871. }
  1872. ///----------------------------------------------------------------------------
  1873. ///
  1874. /// Instr::ReplaceDst
  1875. ///
  1876. /// Unlink this dst from this instr, free it, and replace it with newDst.
  1877. /// The new dst is returned.
  1878. ///
  1879. ///----------------------------------------------------------------------------
  1880. Opnd *
  1881. Instr::ReplaceDst(Opnd * newDst)
  1882. {
  1883. this->FreeDst();
  1884. return this->SetDst(newDst);
  1885. }
  1886. ///----------------------------------------------------------------------------
  1887. ///
  1888. /// Instr::SinkDst
  1889. ///
  1890. /// Replace current dst with new symbol, and assign new symbol using the
  1891. /// given opcode to the previous dst.
  1892. ///
  1893. ///----------------------------------------------------------------------------
  1894. Instr *
  1895. Instr::SinkDst(Js::OpCode assignOpcode, RegNum regNum, IR::Instr *insertAfterInstr)
  1896. {
  1897. return SinkDst(assignOpcode, StackSym::New(TyVar, m_func), regNum, insertAfterInstr);
  1898. }
  1899. Instr *
  1900. Instr::SinkDst(Js::OpCode assignOpcode, StackSym * stackSym, RegNum regNum, IR::Instr *insertAfterInstr)
  1901. {
  1902. if(!insertAfterInstr)
  1903. {
  1904. insertAfterInstr = this;
  1905. }
  1906. Opnd *oldDst, *newDst;
  1907. Instr * newInstr;
  1908. IRType type;
  1909. oldDst = this->UnlinkDst();
  1910. type = oldDst->GetType();
  1911. newDst = this->SetDst(RegOpnd::New(stackSym, regNum, type, m_func));
  1912. newInstr = Instr::New(assignOpcode, oldDst, newDst, m_func);
  1913. insertAfterInstr->InsertAfter(newInstr);
  1914. return newInstr;
  1915. }
  1916. IR::Instr *
  1917. Instr::SinkInstrBefore(IR::Instr * instrTarget)
  1918. {
  1919. // Move this instruction down to the target location, preserving
  1920. // the use(s), if necessary, from redefinition between the original
  1921. // location and the new one.
  1922. if (this->m_next == instrTarget)
  1923. {
  1924. return this->m_prev;
  1925. }
  1926. StackSym *sym;
  1927. if (this->m_src1)
  1928. {
  1929. sym = this->m_src1->GetStackSym();
  1930. if (sym && !sym->m_isSingleDef)
  1931. {
  1932. this->HoistSrc1(Js::OpCode::Ld_A);
  1933. }
  1934. if (this->m_src2)
  1935. {
  1936. sym = this->m_src2->GetStackSym();
  1937. if (sym && !sym->m_isSingleDef)
  1938. {
  1939. this->HoistSrc2(Js::OpCode::Ld_A);
  1940. }
  1941. }
  1942. }
  1943. // Move the instruction down to the target. Return the instruction
  1944. // that preceded the sunk instruction at its original location.
  1945. // (This lets the caller find a Ld_A that this call inserted.)
  1946. IR::Instr * instrPrev = this->m_prev;
  1947. this->Unlink();
  1948. instrTarget->InsertBefore(this);
  1949. return instrPrev;
  1950. }
  1951. ///----------------------------------------------------------------------------
  1952. ///
  1953. /// Instr::UnlinkSrc1
  1954. ///
  1955. /// Unlinks the src1 for 'this' instruction.
  1956. ///
  1957. ///----------------------------------------------------------------------------
  1958. Opnd *
  1959. Instr::UnlinkSrc1()
  1960. {
  1961. Opnd * oldSrc = this->m_src1;
  1962. oldSrc->UnUse();
  1963. this->m_src1 = nullptr;
  1964. return oldSrc;
  1965. }
  1966. ///----------------------------------------------------------------------------
  1967. ///
  1968. /// Instr::FreeSrc1
  1969. ///
  1970. /// Unlinks and free the src1 for 'this' instruction.
  1971. ///
  1972. ///----------------------------------------------------------------------------
  1973. void
  1974. Instr::FreeSrc1()
  1975. {
  1976. Opnd * unlinkedSrc;
  1977. unlinkedSrc = this->UnlinkSrc1();
  1978. unlinkedSrc->Free(this->m_func);
  1979. }
  1980. ///----------------------------------------------------------------------------
  1981. ///
  1982. /// Instr::ReplaceSrc1
  1983. ///
  1984. /// Unlink src1 from this instr, free it, and replace it with newSrc.
  1985. /// The new src is returned.
  1986. ///
  1987. ///----------------------------------------------------------------------------
  1988. Opnd *
  1989. Instr::ReplaceSrc1(Opnd * newSrc)
  1990. {
  1991. this->FreeSrc1();
  1992. return this->SetSrc1(newSrc);
  1993. }
  1994. ///----------------------------------------------------------------------------
  1995. ///
  1996. /// Instr::HoistSrc1
  1997. ///
  1998. /// Replace current src with new symbol, and assign new symbol using the
  1999. /// given opcode from the previous src.
  2000. ///
  2001. ///----------------------------------------------------------------------------
  2002. Instr *
  2003. Instr::HoistSrc1(Js::OpCode assignOpcode, RegNum regNum, StackSym *newSym)
  2004. {
  2005. Opnd *oldSrc, *newSrc;
  2006. Instr * newInstr;
  2007. IRType type;
  2008. oldSrc = this->UnlinkSrc1();
  2009. type = oldSrc->GetType();
  2010. const bool creatingNewSym = !newSym;
  2011. if(creatingNewSym)
  2012. {
  2013. newSym = StackSym::New(type, m_func);
  2014. }
  2015. newSrc = this->SetSrc1(RegOpnd::New(newSym, regNum, type, m_func));
  2016. newSrc->SetValueType(oldSrc->GetValueType());
  2017. newInstr = Instr::New(assignOpcode, newSrc, oldSrc, m_func);
  2018. this->InsertBefore(newInstr);
  2019. if(creatingNewSym)
  2020. {
  2021. if (oldSrc->IsRegOpnd())
  2022. {
  2023. newSym->CopySymAttrs(oldSrc->AsRegOpnd()->m_sym);
  2024. }
  2025. else if (oldSrc->IsImmediateOpnd())
  2026. {
  2027. newSym->SetIsConst();
  2028. }
  2029. }
  2030. return newInstr;
  2031. }
  2032. ///----------------------------------------------------------------------------
  2033. ///
  2034. /// Instr::UnlinkSrc2
  2035. ///
  2036. /// Unlinks the src2 for 'this' instruction.
  2037. ///
  2038. ///----------------------------------------------------------------------------
  2039. Opnd *
  2040. Instr::UnlinkSrc2()
  2041. {
  2042. Opnd * oldSrc = this->m_src2;
  2043. oldSrc->UnUse();
  2044. this->m_src2 = nullptr;
  2045. return oldSrc;
  2046. }
  2047. ///----------------------------------------------------------------------------
  2048. ///
  2049. /// Instr::FreeSrc2
  2050. ///
  2051. /// Unlinks and free the src2 for 'this' instruction.
  2052. ///
  2053. ///----------------------------------------------------------------------------
  2054. void
  2055. Instr::FreeSrc2()
  2056. {
  2057. Opnd * unlinkedSrc;
  2058. unlinkedSrc = this->UnlinkSrc2();
  2059. unlinkedSrc->Free(this->m_func);
  2060. }
  2061. ///----------------------------------------------------------------------------
  2062. ///
  2063. /// Instr::ReplaceSrc2
  2064. ///
  2065. /// Unlink src2 from this instr, free it, and replace it with newSrc.
  2066. /// The new src is returned.
  2067. ///
  2068. ///----------------------------------------------------------------------------
  2069. Opnd *
  2070. Instr::ReplaceSrc2(Opnd * newSrc)
  2071. {
  2072. this->FreeSrc2();
  2073. return this->SetSrc2(newSrc);
  2074. }
  2075. ///----------------------------------------------------------------------------
  2076. ///
  2077. /// Instr::HoistSrc2
  2078. ///
  2079. /// Replace current src with new symbol, and assign new symbol using the
  2080. /// given opcode from the previous src.
  2081. ///
  2082. ///----------------------------------------------------------------------------
  2083. Instr *
  2084. Instr::HoistSrc2(Js::OpCode assignOpcode, RegNum regNum, StackSym *newSym)
  2085. {
  2086. Opnd *oldSrc, *newSrc;
  2087. Instr * newInstr;
  2088. IRType type;
  2089. oldSrc = this->UnlinkSrc2();
  2090. type = oldSrc->GetType();
  2091. const bool creatingNewSym = !newSym;
  2092. if(creatingNewSym)
  2093. {
  2094. newSym = StackSym::New(type, m_func);
  2095. }
  2096. newSrc = this->SetSrc2(RegOpnd::New(newSym, regNum, type, m_func));
  2097. newSrc->SetValueType(oldSrc->GetValueType());
  2098. newInstr = Instr::New(assignOpcode, newSrc, oldSrc, m_func);
  2099. this->InsertBefore(newInstr);
  2100. if(creatingNewSym)
  2101. {
  2102. if (oldSrc->IsRegOpnd())
  2103. {
  2104. newSym->CopySymAttrs(oldSrc->AsRegOpnd()->m_sym);
  2105. }
  2106. else if (oldSrc->IsIntConstOpnd())
  2107. {
  2108. newSym->SetIsIntConst(oldSrc->AsIntConstOpnd()->GetValue());
  2109. }
  2110. }
  2111. return newInstr;
  2112. }
  2113. ///----------------------------------------------------------------------------
  2114. ///
  2115. /// Instr::HoistIndirOffset
  2116. ///
  2117. /// Replace the offset of the given indir with a new symbol, which becomes the indir index.
  2118. /// Assign the new symbol by creating an assignment from the constant offset.
  2119. ///
  2120. ///----------------------------------------------------------------------------
  2121. Instr *
  2122. Instr::HoistIndirOffset(IR::IndirOpnd *indirOpnd, RegNum regNum)
  2123. {
  2124. int32 offset = indirOpnd->GetOffset();
  2125. if (indirOpnd->GetIndexOpnd())
  2126. {
  2127. return HoistIndirOffsetAsAdd(indirOpnd, indirOpnd->GetBaseOpnd(), offset, regNum);
  2128. }
  2129. IntConstOpnd *offsetOpnd = IntConstOpnd::New(offset, TyInt32, this->m_func);
  2130. RegOpnd *indexOpnd = RegOpnd::New(StackSym::New(TyMachReg, this->m_func), regNum, TyMachReg, this->m_func);
  2131. #if defined(DBG) && defined(_M_ARM)
  2132. if (regNum == SCRATCH_REG)
  2133. {
  2134. AssertMsg(indirOpnd->GetBaseOpnd()->GetReg()!= SCRATCH_REG, "Why both are SCRATCH_REG");
  2135. if (this->GetSrc1() && this->GetSrc1()->IsRegOpnd())
  2136. {
  2137. Assert(this->GetSrc1()->AsRegOpnd()->GetReg() != SCRATCH_REG);
  2138. }
  2139. if (this->GetSrc2() && this->GetSrc2()->IsRegOpnd())
  2140. {
  2141. Assert(this->GetSrc2()->AsRegOpnd()->GetReg() != SCRATCH_REG);
  2142. }
  2143. if (this->GetDst() && this->GetDst()->IsRegOpnd())
  2144. {
  2145. Assert(this->GetDst()->AsRegOpnd()->GetReg() != SCRATCH_REG);
  2146. }
  2147. }
  2148. #endif
  2149. // Clear the offset and add a new reg as the index.
  2150. indirOpnd->SetOffset(0);
  2151. indirOpnd->SetIndexOpnd(indexOpnd);
  2152. Instr *instrAssign = LowererMD::CreateAssign(indexOpnd, offsetOpnd, this);
  2153. indexOpnd->m_sym->SetIsIntConst(offset);
  2154. return instrAssign;
  2155. }
  2156. IndirOpnd *
  2157. Instr::HoistMemRefAddress(MemRefOpnd *const memRefOpnd, const Js::OpCode loadOpCode)
  2158. {
  2159. Assert(memRefOpnd);
  2160. #if defined(_M_IX86) || defined(_M_X64)
  2161. Assert(!LowererMDArch::IsLegalMemLoc(memRefOpnd));
  2162. #endif
  2163. intptr_t address = memRefOpnd->GetMemLoc();
  2164. IR::AddrOpndKind kind = memRefOpnd->GetAddrKind();
  2165. Func *const func = m_func;
  2166. IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(address, kind, this->m_func, true);
  2167. IR::IndirOpnd * indirOpnd = func->GetTopFunc()->GetConstantAddressIndirOpnd(address, addrOpnd, kind, memRefOpnd->GetType(), loadOpCode);
  2168. if (indirOpnd == nullptr)
  2169. {
  2170. IR::RegOpnd * addressRegOpnd = IR::RegOpnd::New(TyMachPtr, func);
  2171. IR::Instr *const newInstr =
  2172. IR::Instr::New(
  2173. loadOpCode,
  2174. addressRegOpnd,
  2175. IR::AddrOpnd::New(address, kind, func, true),
  2176. func);
  2177. InsertBefore(newInstr);
  2178. indirOpnd = IR::IndirOpnd::New(addressRegOpnd, 0, memRefOpnd->GetType(), func, true);
  2179. #if DBG_DUMP
  2180. // TODO: michhol oop jit, make intptr
  2181. indirOpnd->SetAddrKind(kind, (void*)address);
  2182. #endif
  2183. }
  2184. return DeepReplace(memRefOpnd, indirOpnd)->AsIndirOpnd();
  2185. }
  2186. Opnd *
  2187. Instr::Replace(Opnd *oldOpnd, Opnd *newOpnd)
  2188. {
  2189. if (oldOpnd == this->GetDst())
  2190. {
  2191. return this->ReplaceDst(newOpnd);
  2192. }
  2193. else
  2194. {
  2195. return this->ReplaceSrc(oldOpnd, newOpnd);
  2196. }
  2197. }
  2198. Opnd *Instr::DeepReplace(Opnd *const oldOpnd, Opnd *const newOpnd)
  2199. {
  2200. Assert(oldOpnd);
  2201. Assert(newOpnd);
  2202. IR::Opnd *opnd = GetDst();
  2203. if(opnd && oldOpnd != opnd && oldOpnd->IsEqual(opnd))
  2204. {
  2205. ReplaceDst(newOpnd);
  2206. }
  2207. opnd = GetSrc1();
  2208. if(opnd && oldOpnd != opnd && oldOpnd->IsEqual(opnd))
  2209. {
  2210. ReplaceSrc1(newOpnd);
  2211. }
  2212. opnd = GetSrc2();
  2213. if(opnd && oldOpnd != opnd && oldOpnd->IsEqual(opnd))
  2214. {
  2215. ReplaceSrc2(newOpnd);
  2216. }
  2217. // Do this last because Replace will delete oldOpnd
  2218. return Replace(oldOpnd, newOpnd);
  2219. }
  2220. Instr *
  2221. Instr::HoistIndirOffsetAsAdd(IR::IndirOpnd *orgOpnd, IR::Opnd *baseOpnd, int offset, RegNum regNum)
  2222. {
  2223. IR::RegOpnd *newBaseOpnd = IR::RegOpnd::New(StackSym::New(TyMachPtr, this->m_func), regNum, TyMachPtr, this->m_func);
  2224. IR::IntConstOpnd *src2 = IR::IntConstOpnd::New(offset, TyInt32, this->m_func);
  2225. IR::Instr * instrAdd = IR::Instr::New(Js::OpCode::ADD, newBaseOpnd, baseOpnd, src2, this->m_func);
  2226. this->InsertBefore(instrAdd);
  2227. orgOpnd->ReplaceBaseOpnd(newBaseOpnd);
  2228. orgOpnd->SetOffset(0);
  2229. return instrAdd;
  2230. }
  2231. Instr *
  2232. Instr::HoistIndirIndexOpndAsAdd(IR::IndirOpnd *orgOpnd, IR::Opnd *baseOpnd, IR::Opnd *indexOpnd, RegNum regNum)
  2233. {
  2234. IR::RegOpnd *newBaseOpnd = IR::RegOpnd::New(StackSym::New(TyMachPtr, this->m_func), regNum, TyMachPtr, this->m_func);
  2235. IR::Instr * instrAdd = IR::Instr::New(Js::OpCode::ADD, newBaseOpnd, baseOpnd, indexOpnd, this->m_func);
  2236. this->InsertBefore(instrAdd);
  2237. orgOpnd->ReplaceBaseOpnd(newBaseOpnd);
  2238. orgOpnd->SetIndexOpnd(nullptr);
  2239. return instrAdd;
  2240. }
  2241. Instr *
  2242. Instr::HoistSymOffsetAsAdd(IR::SymOpnd *orgOpnd, IR::Opnd *baseOpnd, int offset, RegNum regNum)
  2243. {
  2244. IR::IndirOpnd *newIndirOpnd = IR::IndirOpnd::New(baseOpnd->AsRegOpnd(), 0, TyMachPtr, this->m_func);
  2245. this->Replace(orgOpnd, newIndirOpnd); // Replace SymOpnd with IndirOpnd
  2246. return this->HoistIndirOffsetAsAdd(newIndirOpnd, baseOpnd, offset, regNum);
  2247. }
  2248. ///----------------------------------------------------------------------------
  2249. ///
  2250. /// Instr::HoistSymOffset
  2251. ///
  2252. /// Replace the given sym with an indir using the given base and offset.
  2253. /// (This is used, for instance, to hoist a sym offset that is too large to encode.)
  2254. ///
  2255. ///----------------------------------------------------------------------------
  2256. Instr *
  2257. Instr::HoistSymOffset(SymOpnd *symOpnd, RegNum baseReg, uint32 offset, RegNum regNum)
  2258. {
  2259. IR::RegOpnd *baseOpnd = IR::RegOpnd::New(nullptr, baseReg, TyMachPtr, this->m_func);
  2260. IR::IndirOpnd *indirOpnd = IR::IndirOpnd::New(baseOpnd, offset, symOpnd->GetType(), this->m_func);
  2261. if (symOpnd == this->GetDst())
  2262. {
  2263. this->ReplaceDst(indirOpnd);
  2264. }
  2265. else
  2266. {
  2267. this->ReplaceSrc(symOpnd, indirOpnd);
  2268. }
  2269. return this->HoistIndirOffset(indirOpnd, regNum);
  2270. }
  2271. Opnd *
  2272. Instr::UnlinkSrc(Opnd *src)
  2273. {
  2274. if (src == this->GetSrc1())
  2275. {
  2276. return this->UnlinkSrc1();
  2277. }
  2278. else
  2279. {
  2280. AssertMsg(src == this->GetSrc2(), "Src not found");
  2281. return this->UnlinkSrc2();
  2282. }
  2283. }
  2284. ///----------------------------------------------------------------------------
  2285. ///
  2286. /// Instr::ReplaceSrc
  2287. ///
  2288. /// Unlink oldSrc from this instr, free it, and replace it with newSrc.
  2289. /// The new src is returned.
  2290. ///
  2291. ///----------------------------------------------------------------------------
  2292. Opnd *
  2293. Instr::ReplaceSrc(Opnd *oldSrc, Opnd * newSrc)
  2294. {
  2295. if (oldSrc == this->GetSrc1())
  2296. {
  2297. return this->ReplaceSrc1(newSrc);
  2298. }
  2299. else
  2300. {
  2301. AssertMsg(oldSrc == this->GetSrc2(), "OldSrc not found");
  2302. return this->ReplaceSrc2(newSrc);
  2303. }
  2304. }
  2305. ///----------------------------------------------------------------------------
  2306. ///
  2307. /// Instr::IsRealInstr
  2308. ///
  2309. /// Does this instr generate code?
  2310. ///
  2311. ///----------------------------------------------------------------------------
  2312. bool
  2313. Instr::IsRealInstr() const
  2314. {
  2315. switch (m_opcode)
  2316. {
  2317. case Js::OpCode::Label:
  2318. case Js::OpCode::StatementBoundary:
  2319. case Js::OpCode::NoImplicitCallUses:
  2320. case Js::OpCode::NoIntOverflowBoundary:
  2321. return false;
  2322. default:
  2323. return true;
  2324. }
  2325. }
  2326. ///----------------------------------------------------------------------------
  2327. ///
  2328. /// Instr::GetNextRealInstr
  2329. ///
  2330. ///----------------------------------------------------------------------------
  2331. IR::Instr *
  2332. Instr::GetNextRealInstr() const
  2333. {
  2334. IR::Instr *instr = this->m_next;
  2335. while (instr != nullptr && !instr->IsRealInstr())
  2336. {
  2337. AssertMsg(instr->m_next || instr->IsPragmaInstr(), "GetNextRealInstr() failed...");
  2338. instr = instr->m_next;
  2339. }
  2340. return instr;
  2341. }
  2342. ///----------------------------------------------------------------------------
  2343. ///
  2344. /// Instr::GetNextRealInstrOrLabel
  2345. ///
  2346. ///----------------------------------------------------------------------------
  2347. IR::Instr *
  2348. Instr::GetNextRealInstrOrLabel() const
  2349. {
  2350. IR::Instr *instr = this->m_next;
  2351. while (instr != nullptr && !instr->IsLabelInstr() && !instr->IsRealInstr())
  2352. {
  2353. instr = instr->m_next;
  2354. AssertMsg(instr, "GetNextRealInstrOrLabel() failed...");
  2355. }
  2356. return instr;
  2357. }
  2358. IR::Instr *
  2359. Instr::GetNextBranchOrLabel() const
  2360. {
  2361. IR::Instr *instr = this->m_next;
  2362. while (instr != nullptr && !instr->IsLabelInstr() && !instr->IsBranchInstr())
  2363. {
  2364. instr = instr->m_next;
  2365. }
  2366. return instr;
  2367. }
  2368. ///----------------------------------------------------------------------------
  2369. ///
  2370. /// Instr::GetPrevRealInstr
  2371. ///
  2372. ///----------------------------------------------------------------------------
  2373. IR::Instr *
  2374. Instr::GetPrevRealInstr() const
  2375. {
  2376. IR::Instr *instr = this->m_prev;
  2377. while (!instr->IsRealInstr())
  2378. {
  2379. instr = instr->m_prev;
  2380. AssertMsg(instr, "GetPrevRealInstr() failed...");
  2381. }
  2382. return instr;
  2383. }
  2384. ///----------------------------------------------------------------------------
  2385. ///
  2386. /// Instr::GetPrevRealInstrOrLabel
  2387. ///
  2388. ///----------------------------------------------------------------------------
  2389. IR::Instr *
  2390. Instr::GetPrevRealInstrOrLabel() const
  2391. {
  2392. IR::Instr *instr = this->m_prev;
  2393. while (!instr->IsLabelInstr() && !instr->IsRealInstr())
  2394. {
  2395. instr = instr->m_prev;
  2396. AssertMsg(instr, "GetPrevRealInstrOrLabel() failed...");
  2397. }
  2398. return instr;
  2399. }
  2400. ///----------------------------------------------------------------------------
  2401. ///
  2402. /// Instr::GetInsertBeforeByteCodeUsesInstr
  2403. /// Finds the instruction before which new instructions can be inserted, by skipping ByteCodeUses instructions associated with
  2404. /// this instruction.
  2405. ///
  2406. ///----------------------------------------------------------------------------
  2407. IR::Instr *Instr::GetInsertBeforeByteCodeUsesInstr()
  2408. {
  2409. const uint32 byteCodeOffset = GetByteCodeOffset();
  2410. IR::Instr *insertBeforeInstr = this;
  2411. IR::Instr *prevInstr = insertBeforeInstr->m_prev;
  2412. while(prevInstr && prevInstr->IsByteCodeUsesInstr() && prevInstr->GetByteCodeOffset() == byteCodeOffset)
  2413. {
  2414. insertBeforeInstr = prevInstr;
  2415. prevInstr = prevInstr->m_prev;
  2416. }
  2417. return insertBeforeInstr;
  2418. }
  2419. ///----------------------------------------------------------------------------
  2420. ///
  2421. /// Instr::GetOrCreateContinueLabel
  2422. ///
  2423. ///----------------------------------------------------------------------------
  2424. IR::LabelInstr *
  2425. Instr::GetOrCreateContinueLabel(const bool isHelper)
  2426. {
  2427. if(m_next && m_next->IsLabelInstr() && m_next->AsLabelInstr()->isOpHelper == isHelper)
  2428. {
  2429. return m_next->AsLabelInstr();
  2430. }
  2431. IR::LabelInstr *const label = IR::LabelInstr::New(Js::OpCode::Label, m_func, isHelper);
  2432. InsertAfter(label);
  2433. return label;
  2434. }
  2435. ///----------------------------------------------------------------------------
  2436. ///
  2437. /// Instr::FindRegUse
  2438. ///
  2439. /// Search a reg use of the given sym. Return the RegOpnd that uses it.
  2440. ///
  2441. ///----------------------------------------------------------------------------
  2442. IR::RegOpnd *
  2443. Instr::FindRegUse(StackSym *sym)
  2444. {
  2445. IR::Opnd *src1 = this->GetSrc1();
  2446. // Check src1
  2447. if (src1)
  2448. {
  2449. if (src1->IsRegOpnd())
  2450. {
  2451. RegOpnd *regOpnd = src1->AsRegOpnd();
  2452. if (regOpnd->m_sym == sym)
  2453. {
  2454. return regOpnd;
  2455. }
  2456. }
  2457. else if (src1->IsIndirOpnd())
  2458. {
  2459. IR::IndirOpnd *indirOpnd = src1->AsIndirOpnd();
  2460. if (indirOpnd->GetBaseOpnd()->m_sym == sym)
  2461. {
  2462. return indirOpnd->GetBaseOpnd();
  2463. }
  2464. else if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == sym)
  2465. {
  2466. return indirOpnd->GetIndexOpnd();
  2467. }
  2468. }
  2469. IR::Opnd *src2 = this->GetSrc2();
  2470. // Check src2
  2471. if (src2)
  2472. {
  2473. if (src2->IsRegOpnd())
  2474. {
  2475. RegOpnd *regOpnd = src2->AsRegOpnd();
  2476. if (regOpnd->m_sym == sym)
  2477. {
  2478. return regOpnd;
  2479. }
  2480. }
  2481. else if (src2->IsIndirOpnd())
  2482. {
  2483. IR::IndirOpnd *indirOpnd = src2->AsIndirOpnd();
  2484. if (indirOpnd->GetBaseOpnd()->m_sym == sym)
  2485. {
  2486. return indirOpnd->GetBaseOpnd();
  2487. }
  2488. else if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == sym)
  2489. {
  2490. return indirOpnd->GetIndexOpnd();
  2491. }
  2492. }
  2493. }
  2494. }
  2495. // Check uses in dst
  2496. IR::Opnd *dst = this->GetDst();
  2497. if (dst != nullptr && dst->IsIndirOpnd())
  2498. {
  2499. IR::IndirOpnd *indirOpnd = dst->AsIndirOpnd();
  2500. if (indirOpnd->GetBaseOpnd()->m_sym == sym)
  2501. {
  2502. return indirOpnd->GetBaseOpnd();
  2503. }
  2504. else if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == sym)
  2505. {
  2506. return indirOpnd->GetIndexOpnd();
  2507. }
  2508. }
  2509. return nullptr;
  2510. }
  2511. IR::RegOpnd *
  2512. Instr::FindRegUseInRange(StackSym *sym, IR::Instr *instrBegin, IR::Instr *instrEnd)
  2513. {
  2514. FOREACH_INSTR_IN_RANGE(instr, instrBegin, instrEnd)
  2515. {
  2516. Assert(instr);
  2517. IR::RegOpnd *opnd = instr->FindRegUse(sym);
  2518. if (opnd)
  2519. {
  2520. return opnd;
  2521. }
  2522. }
  2523. NEXT_INSTR_IN_RANGE;
  2524. return nullptr;
  2525. }
  2526. ///----------------------------------------------------------------------------
  2527. ///
  2528. /// Instr::FindRegDef
  2529. ///
  2530. /// Search a reg def of the given sym. Return the RegOpnd that defines it.
  2531. ///
  2532. ///----------------------------------------------------------------------------
  2533. IR::RegOpnd *
  2534. Instr::FindRegDef(StackSym *sym)
  2535. {
  2536. IR::Opnd *dst = this->GetDst();
  2537. if (dst)
  2538. {
  2539. if (dst->IsRegOpnd())
  2540. {
  2541. RegOpnd *regOpnd = dst->AsRegOpnd();
  2542. if (regOpnd->m_sym == sym)
  2543. {
  2544. return regOpnd;
  2545. }
  2546. }
  2547. }
  2548. return nullptr;
  2549. }
  2550. Instr*
  2551. Instr::FindSingleDefInstr(Js::OpCode opCode, Opnd* src)
  2552. {
  2553. RegOpnd* src1 = src->IsRegOpnd() ? src->AsRegOpnd() : nullptr;
  2554. return src1 &&
  2555. src1->m_sym->IsSingleDef() &&
  2556. src1->m_sym->GetInstrDef()->m_opcode == opCode ?
  2557. src1->m_sym->GetInstrDef() :
  2558. nullptr;
  2559. }
  2560. void
  2561. Instr::TransferDstAttributesTo(Instr * instr)
  2562. {
  2563. instr->dstIsTempNumber = this->dstIsTempNumber;
  2564. instr->dstIsTempNumberTransferred = this->dstIsTempNumberTransferred;
  2565. instr->dstIsTempObject = this->dstIsTempObject;
  2566. }
  2567. void
  2568. Instr::TransferTo(Instr * instr)
  2569. {
  2570. Assert(instr->m_dst == nullptr);
  2571. Assert(instr->m_src1 == nullptr);
  2572. Assert(instr->m_src2 == nullptr);
  2573. this->TransferDstAttributesTo(instr);
  2574. instr->usesStackArgumentsObject = this->usesStackArgumentsObject;
  2575. instr->isCloned = this->isCloned;
  2576. instr->ignoreNegativeZero = this->ignoreNegativeZero;
  2577. instr->ignoreIntOverflow = this->ignoreIntOverflow;
  2578. instr->ignoreIntOverflowInRange = this->ignoreIntOverflowInRange;
  2579. instr->ignoreOverflowBitCount = this->ignoreOverflowBitCount;
  2580. instr->loadedArrayHeadSegment = this->loadedArrayHeadSegment;
  2581. instr->loadedArrayHeadSegmentLength = this->loadedArrayHeadSegmentLength;
  2582. instr->extractedUpperBoundCheckWithoutHoisting = this->extractedUpperBoundCheckWithoutHoisting;
  2583. instr->m_number = this->m_number;
  2584. instr->m_src1 = this->m_src1;
  2585. instr->m_src2 = this->m_src2;
  2586. instr->dstIsAlwaysConvertedToInt32 = this->dstIsAlwaysConvertedToInt32;
  2587. instr->dstIsAlwaysConvertedToNumber = this->dstIsAlwaysConvertedToNumber;
  2588. instr->dataWidth = this->dataWidth;
  2589. IR::Opnd * dst = this->m_dst;
  2590. if (dst)
  2591. {
  2592. instr->m_dst = dst;
  2593. this->m_dst = nullptr;
  2594. if (dst->IsRegOpnd())
  2595. {
  2596. Sym * sym = dst->AsRegOpnd()->m_sym;
  2597. if (sym->IsStackSym() && sym->AsStackSym()->m_isSingleDef)
  2598. {
  2599. Assert(sym->AsStackSym()->m_instrDef == this);
  2600. StackSym * stackSym = sym->AsStackSym();
  2601. stackSym->m_instrDef = instr;
  2602. }
  2603. }
  2604. }
  2605. this->m_src1 = nullptr;
  2606. this->m_src2 = nullptr;
  2607. }
  2608. IR::Instr *
  2609. Instr::ConvertToBailOutInstr(IR::Instr * bailOutTarget, IR::BailOutKind kind, uint32 bailOutOffset)
  2610. {
  2611. Func * func = bailOutTarget->m_func;
  2612. BailOutInfo * bailOutInfo = JitAnew(func->m_alloc, BailOutInfo, bailOutOffset == Js::Constants::NoByteCodeOffset ? bailOutTarget->GetByteCodeOffset() : bailOutOffset , func);
  2613. #if ENABLE_DEBUG_CONFIG_OPTIONS
  2614. bailOutInfo->bailOutOpcode = this->m_opcode;
  2615. #endif
  2616. return this->ConvertToBailOutInstr(bailOutInfo, kind);
  2617. }
  2618. // Notes:
  2619. // - useAuxBailout = true specifies that this bailout further will be invisible to globopt, etc, and we'll use auxBailoutKind instead of BailoutKind.
  2620. // Currently this is used for BailOutIgnoreException for debugger.
  2621. //
  2622. // Here's typical workflow for scenario useAuxBailout = true.
  2623. // - IRBuilder::Build calls this with kind == BailOutIgnoreException
  2624. // - In here we save the kind to auxBailOut and save bail out info but set hasBailOutInfo to false.
  2625. // - During globopt optimizations presence of this bail out is not detected and instrs can add/remove bailouts as they need.
  2626. // - If they call to convert this instr to bail out instr, we set bailOutKind to what they want and replace bailOutInfo.
  2627. // ** This assumes that for aux bail out bailoutInfo does not really matter (if its pre/post op, etc) **
  2628. // - This is the case for ignore exception.
  2629. // - This will cause to share aux bail out with regular bail out.
  2630. // - In globopt right after OptInstr we check if there is aux bail out which wasn't shared with regular bail out,
  2631. // and if it's not, we convert it back to regular bail out.
  2632. IR::Instr *
  2633. Instr::ConvertToBailOutInstr(BailOutInfo * bailOutInfo, IR::BailOutKind kind, bool useAuxBailOut /* = false */)
  2634. {
  2635. Assert(!this->HasBailOutInfo());
  2636. AssertMsg(!useAuxBailOut || !this->HasAuxBailOut(), "Already aux bail out!");
  2637. Assert(!this->HasAuxBailOut() || this->GetAuxBailOutKind() != IR::BailOutInvalid);
  2638. IR::Instr * bailOutInstr = nullptr;
  2639. if (this->HasAuxBailOut())
  2640. {
  2641. // This instr has already been converted to bailout instr. Only possible with aux bail out.
  2642. // Typical scenario is when globopt calls to convert to e.g. BailOutOnImplicitCalls for the instr which
  2643. // was already converted to bail out instr with HasBailOutInfo() == false and HasAuxBailOutInfo() == true,
  2644. // so that aux bail out is hidden in between IRBuilder and lowerer.
  2645. AssertMsg((this->GetAuxBailOutKind() & ~(IR::BailOutIgnoreException | IR::BailOutForceByFlag)) == 0, "Only IR::BailOutIgnoreException|ForceByFlag supported here.");
  2646. // What we rely on here is:
  2647. // - bailout doesn't have any args.
  2648. // - bailout doesn't use offset as we get it from DebuggingFlags at time of bailout.
  2649. // Use prev debugger bailout kind as decoration, while keeping new kind as main.
  2650. this->SetBailOutKind_NoAssert(kind);
  2651. // Clear old (aux) info and set to the new bailOutInfo.
  2652. this->ReplaceBailOutInfo(bailOutInfo);
  2653. bailOutInfo->bailOutInstr = this;
  2654. this->hasBailOutInfo = true;
  2655. bailOutInstr = this;
  2656. }
  2657. else
  2658. {
  2659. switch (this->m_kind)
  2660. {
  2661. case InstrKindInstr:
  2662. bailOutInstr = IR::BailOutInstr::New(this->m_opcode, kind, bailOutInfo, bailOutInfo->bailOutFunc);
  2663. break;
  2664. case InstrKindProfiled:
  2665. bailOutInstr = IR::ProfiledBailOutInstr::New(this->m_opcode, kind, bailOutInfo, bailOutInfo->bailOutFunc);
  2666. bailOutInstr->AsProfiledInstr()->u = this->AsProfiledInstr()->u;
  2667. break;
  2668. case InstrKindBranch:
  2669. {
  2670. IR::BranchInstr * branchInstr = this->AsBranchInstr();
  2671. Assert(!branchInstr->IsMultiBranch());
  2672. IR::BranchBailOutInstr * branchBailOutInstr = IR::BranchBailOutInstr::New(this->m_opcode, kind, bailOutInfo, bailOutInfo->bailOutFunc);
  2673. branchBailOutInstr->SetTarget(branchInstr->GetTarget());
  2674. branchBailOutInstr->SetByteCodeReg(branchInstr->GetByteCodeReg());
  2675. bailOutInstr = branchBailOutInstr;
  2676. break;
  2677. }
  2678. default:
  2679. AnalysisAssert(false);
  2680. };
  2681. this->m_next->m_prev = bailOutInstr;
  2682. this->m_prev->m_next = bailOutInstr;
  2683. bailOutInstr->m_next = this->m_next;
  2684. bailOutInstr->m_prev = this->m_prev;
  2685. this->TransferTo(bailOutInstr);
  2686. this->Free();
  2687. }
  2688. if (useAuxBailOut)
  2689. {
  2690. // Move bail out kind from bailOutKind to auxBailOutKind and hide bailOutInfo as if this is not a bail out instr.
  2691. bailOutInstr->SetAuxBailOutKind(kind);
  2692. bailOutInstr->SetBailOutKind_NoAssert(IR::BailOutInvalid);
  2693. bailOutInstr->hasBailOutInfo = false;
  2694. bailOutInstr->hasAuxBailOut = true;
  2695. }
  2696. return bailOutInstr;
  2697. }
  2698. // Convert aux bailout to regular bail out.
  2699. // Called by globopt after all optimizations are done, in case we still have aux bail out on the instr.
  2700. void Instr::PromoteAuxBailOut()
  2701. {
  2702. Assert(!this->HasBailOutInfo());
  2703. Assert(this->GetAuxBailOutKind() != IR::BailOutInvalid);
  2704. this->SetBailOutKind_NoAssert(this->GetAuxBailOutKind());
  2705. this->SetAuxBailOutKind(IR::BailOutInvalid);
  2706. this->hasBailOutInfo = true;
  2707. this->hasAuxBailOut = false;
  2708. }
  2709. // Reset all tracks of aux bailout but don't rest the bail out info.
  2710. // Used after we extract aux bail out in lowerer.
  2711. void Instr::ResetAuxBailOut()
  2712. {
  2713. this->SetAuxBailOutKind(IR::BailOutInvalid);
  2714. this->hasAuxBailOut = false;
  2715. }
  2716. void
  2717. Instr::ClearBailOutInfo()
  2718. {
  2719. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  2720. {
  2721. BailOutInfo * bailOutInfo = this->GetBailOutInfo();
  2722. Assert(bailOutInfo);
  2723. if (bailOutInfo->bailOutInstr == this)
  2724. {
  2725. JitArenaAllocator * alloc = this->m_func->m_alloc;
  2726. bailOutInfo->Clear(alloc);
  2727. JitAdelete(alloc, bailOutInfo);
  2728. }
  2729. this->hasBailOutInfo = false;
  2730. this->hasAuxBailOut = false;
  2731. }
  2732. }
  2733. bool Instr::HasAnyLoadHeapArgsOpCode()
  2734. {
  2735. switch (m_opcode)
  2736. {
  2737. case Js::OpCode::LdHeapArguments:
  2738. case Js::OpCode::LdHeapArgsCached:
  2739. case Js::OpCode::LdLetHeapArguments:
  2740. case Js::OpCode::LdLetHeapArgsCached:
  2741. return true;
  2742. }
  2743. return false;
  2744. }
  2745. bool Instr::CanHaveArgOutChain() const
  2746. {
  2747. return
  2748. this->m_opcode == Js::OpCode::CallI ||
  2749. this->m_opcode == Js::OpCode::CallIFixed ||
  2750. this->m_opcode == Js::OpCode::NewScObject ||
  2751. this->m_opcode == Js::OpCode::NewScObjectSpread ||
  2752. this->m_opcode == Js::OpCode::NewScObjArray ||
  2753. this->m_opcode == Js::OpCode::NewScObjArraySpread;
  2754. }
  2755. bool Instr::HasEmptyArgOutChain(IR::Instr** startCallInstrOut)
  2756. {
  2757. Assert(CanHaveArgOutChain());
  2758. if (GetSrc2()->IsRegOpnd())
  2759. {
  2760. IR::RegOpnd * argLinkOpnd = GetSrc2()->AsRegOpnd();
  2761. StackSym *argLinkSym = argLinkOpnd->m_sym->AsStackSym();
  2762. AssertMsg(!argLinkSym->IsArgSlotSym() && argLinkSym->m_isSingleDef, "Arg tree not single def...");
  2763. IR::Instr* startCallInstr = argLinkSym->m_instrDef;
  2764. AssertMsg(startCallInstr->m_opcode == Js::OpCode::StartCall, "Problem with arg chain.");
  2765. if (startCallInstrOut != nullptr)
  2766. {
  2767. *startCallInstrOut = startCallInstr;
  2768. }
  2769. return true;
  2770. }
  2771. return false;
  2772. }
  2773. bool Instr::HasFixedFunctionAddressTarget() const
  2774. {
  2775. Assert(
  2776. this->m_opcode == Js::OpCode::CallI ||
  2777. this->m_opcode == Js::OpCode::CallIFixed ||
  2778. this->m_opcode == Js::OpCode::NewScObject ||
  2779. this->m_opcode == Js::OpCode::NewScObjectSpread ||
  2780. this->m_opcode == Js::OpCode::NewScObjArray ||
  2781. this->m_opcode == Js::OpCode::NewScObjArraySpread ||
  2782. this->m_opcode == Js::OpCode::NewScObjectNoCtor);
  2783. return
  2784. this->GetSrc1() != nullptr &&
  2785. this->GetSrc1()->IsAddrOpnd() &&
  2786. this->GetSrc1()->AsAddrOpnd()->GetAddrOpndKind() == IR::AddrOpndKind::AddrOpndKindDynamicVar &&
  2787. this->GetSrc1()->AsAddrOpnd()->m_isFunction;
  2788. }
  2789. void Instr::MoveArgs(bool generateByteCodeCapture)
  2790. {
  2791. Assert(this->m_opcode == Js::OpCode::InlineeStart || this->m_opcode == Js::OpCode::CallDirect ||
  2792. this->m_opcode == Js::OpCode::CallI || this->m_opcode == Js::OpCode::CallIFixed);
  2793. IR::Instr *argInsertInstr = this;
  2794. this->IterateArgInstrs([&](IR::Instr* argInstr)
  2795. {
  2796. if (generateByteCodeCapture)
  2797. {
  2798. argInstr->GenerateBytecodeArgOutCapture();
  2799. }
  2800. argInstr->Move(argInsertInstr);
  2801. argInsertInstr = argInstr;
  2802. return false;
  2803. });
  2804. }
  2805. void Instr::Move(IR::Instr* insertInstr)
  2806. {
  2807. this->Unlink();
  2808. this->ClearByteCodeOffset();
  2809. this->SetByteCodeOffset(insertInstr);
  2810. insertInstr->InsertBefore(this);
  2811. }
  2812. IR::Instr* Instr::GetBytecodeArgOutCapture()
  2813. {
  2814. Assert(this->m_opcode == Js::OpCode::ArgOut_A_Inline ||
  2815. this->m_opcode == Js::OpCode::ArgOut_A ||
  2816. this->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  2817. Assert(this->m_dst->GetStackSym()->m_isArgCaptured);
  2818. IR::Instr* instr = this->GetSrc1()->GetStackSym()->m_instrDef;
  2819. Assert(instr->m_opcode == Js::OpCode::BytecodeArgOutCapture);
  2820. return instr;
  2821. }
  2822. bool Instr::HasByteCodeArgOutCapture()
  2823. {
  2824. Assert(this->m_opcode == Js::OpCode::ArgOut_A_FixupForStackArgs ||
  2825. this->m_opcode == Js::OpCode::ArgOut_A_Inline ||
  2826. this->m_opcode == Js::OpCode::ArgOut_A ||
  2827. this->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn ||
  2828. this->m_opcode == Js::OpCode::ArgOut_A_FromStackArgs);
  2829. if (this->m_dst->GetStackSym()->m_isArgCaptured)
  2830. {
  2831. Assert(GetBytecodeArgOutCapture() != nullptr);
  2832. return true;
  2833. }
  2834. return false;
  2835. }
  2836. void Instr::GenerateBytecodeArgOutCapture()
  2837. {
  2838. if (!HasByteCodeArgOutCapture())
  2839. {
  2840. this->m_dst->GetStackSym()->m_isArgCaptured = true;
  2841. StackSym* tmpSym = StackSym::NewArgSlotRegSym(this->GetDst()->GetStackSym()->GetArgSlotNum(), this->m_func, this->GetDst()->GetType());
  2842. IR::Instr* instr = this->HoistSrc1(Js::OpCode::BytecodeArgOutCapture, RegNOREG, tmpSym);
  2843. instr->SetByteCodeOffset(this);
  2844. }
  2845. }
  2846. void Instr::GenerateArgOutSnapshot()
  2847. {
  2848. StackSym* tmpSym = StackSym::NewArgSlotRegSym(this->GetDst()->GetStackSym()->GetArgSlotNum(), this->m_func);
  2849. IR::Instr* instr = this->HoistSrc1(Js::OpCode::Ld_A, RegNOREG, tmpSym);
  2850. instr->SetByteCodeOffset(this);
  2851. }
  2852. IR::Instr* Instr::GetArgOutSnapshot()
  2853. {
  2854. Assert(this->m_opcode == Js::OpCode::ArgOut_A_FixupForStackArgs);
  2855. IR::Instr* instr = this->GetSrc1()->GetStackSym()->m_instrDef;
  2856. Assert(instr->m_opcode == Js::OpCode::Ld_A);
  2857. return instr;
  2858. }
  2859. bool Instr::HasAnyImplicitCalls() const
  2860. {
  2861. // there can be no implicit calls in asm.js
  2862. if (m_func->GetJITFunctionBody()->IsAsmJsMode())
  2863. {
  2864. return false;
  2865. }
  2866. if (OpCodeAttr::HasImplicitCall(this->m_opcode))
  2867. {
  2868. return true;
  2869. }
  2870. if (OpCodeAttr::OpndHasImplicitCall(this->m_opcode))
  2871. {
  2872. if (this->m_dst &&
  2873. ((this->m_dst->IsSymOpnd() && this->m_dst->AsSymOpnd()->m_sym->IsPropertySym()) ||
  2874. this->m_dst->IsIndirOpnd()))
  2875. {
  2876. return true;
  2877. }
  2878. IR::Opnd *src1 = this->GetSrc1();
  2879. if (src1)
  2880. {
  2881. if ((src1->IsSymOpnd() && src1->AsSymOpnd()->m_sym->IsPropertySym()) || src1->IsIndirOpnd())
  2882. {
  2883. return true;
  2884. }
  2885. if (!src1->GetValueType().IsPrimitive())
  2886. {
  2887. return true;
  2888. }
  2889. IR::Opnd *src2 = this->GetSrc2();
  2890. if (src2)
  2891. {
  2892. if ((src2->IsSymOpnd() && src2->AsSymOpnd()->m_sym->IsPropertySym()) || src2->IsIndirOpnd())
  2893. {
  2894. return true;
  2895. }
  2896. if (!src2->GetValueType().IsPrimitive())
  2897. {
  2898. return true;
  2899. }
  2900. }
  2901. }
  2902. }
  2903. return false;
  2904. }
  2905. bool Instr::HasAnySideEffects() const
  2906. {
  2907. return (hasSideEffects ||
  2908. OpCodeAttr::HasSideEffects(this->m_opcode) ||
  2909. this->HasAnyImplicitCalls());
  2910. }
  2911. bool Instr::AreAllOpndInt64() const
  2912. {
  2913. bool isDstInt64 = !m_dst || IRType_IsInt64(m_dst->GetType());
  2914. bool isSrc1Int64 = !m_src1 || IRType_IsInt64(m_src1->GetType());
  2915. bool isSrc2Int64 = !m_src2 || IRType_IsInt64(m_src2->GetType());
  2916. return isDstInt64 && isSrc1Int64 && isSrc2Int64;
  2917. }
  2918. JITTimeFixedField* Instr::GetFixedFunction() const
  2919. {
  2920. Assert(HasFixedFunctionAddressTarget());
  2921. JITTimeFixedField* function = (JITTimeFixedField*)this->m_src1->AsAddrOpnd()->m_metadata;
  2922. return function;
  2923. }
  2924. IR::Instr* Instr::GetNextArg()
  2925. {
  2926. Assert(this->m_opcode == Js::OpCode::ArgOut_A_FixupForStackArgs ||
  2927. this->m_opcode == Js::OpCode::ArgOut_A_Inline ||
  2928. this->m_opcode == Js::OpCode::ArgOut_A ||
  2929. this->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn ||
  2930. this->m_opcode == Js::OpCode::InlineeStart);
  2931. IR::Instr* argInstr = this;
  2932. while (true)
  2933. {
  2934. StackSym* linkSym;
  2935. if (argInstr->GetSrc2()->IsRegOpnd())
  2936. {
  2937. linkSym = argInstr->GetSrc2()->AsRegOpnd()->m_sym->AsStackSym();
  2938. }
  2939. else
  2940. {
  2941. linkSym = argInstr->GetSrc2()->AsSymOpnd()->m_sym->AsStackSym();
  2942. Assert(linkSym->IsArgSlotSym());
  2943. }
  2944. Assert(linkSym->IsSingleDef());
  2945. argInstr = linkSym->m_instrDef;
  2946. if (argInstr->m_opcode == Js::OpCode::ArgOut_A_InlineSpecialized)
  2947. {
  2948. continue;
  2949. }
  2950. if (argInstr->m_opcode == Js::OpCode::StartCall)
  2951. {
  2952. break;
  2953. }
  2954. return argInstr;
  2955. }
  2956. return nullptr;
  2957. }
  2958. uint Instr::GetArgOutCount(bool getInterpreterArgOutCount)
  2959. {
  2960. // There are cases of inlining like .apply and .call target inlining, where we muck around with the ArgOut sequence,
  2961. // and make it different from the one the interpreter sees (and expects, on a bailout).
  2962. // In such cases, we set the interpreter version of the number of ArgOuts as the src2 of StartCall,
  2963. // and any code that queries the argout count for bailout purposes should look at the src2 (if available) of these instructions.
  2964. // If the src2 is not set, that means that the interpreter and the JIT versions of the argout count are the same.
  2965. Js::OpCode opcode = this->m_opcode;
  2966. Assert(opcode == Js::OpCode::StartCall ||
  2967. opcode == Js::OpCode::InlineeEnd || opcode == Js::OpCode::InlineBuiltInEnd|| opcode == Js::OpCode::InlineNonTrackingBuiltInEnd ||
  2968. opcode == Js::OpCode::EndCallForPolymorphicInlinee || opcode == Js::OpCode::LoweredStartCall);
  2969. if (!getInterpreterArgOutCount)
  2970. {
  2971. return this->GetSrc1()->AsIntConstOpnd()->AsUint32();
  2972. }
  2973. Assert(opcode == Js::OpCode::StartCall);
  2974. IntConstType argOutCount = !this->GetSrc2() ? this->GetSrc1()->AsIntConstOpnd()->GetValue() : this->GetSrc2()->AsIntConstOpnd()->GetValue();
  2975. Assert(argOutCount >= 0 && argOutCount < UINT32_MAX);
  2976. return (uint)argOutCount;
  2977. }
  2978. PropertySymOpnd *Instr::GetPropertySymOpnd() const
  2979. {
  2980. if (m_src1 && m_src1->IsSymOpnd() && m_src1->AsSymOpnd()->IsPropertySymOpnd())
  2981. {
  2982. return m_src1->AsPropertySymOpnd();
  2983. }
  2984. if (m_dst && m_dst->IsSymOpnd() && m_dst->AsSymOpnd()->IsPropertySymOpnd())
  2985. {
  2986. return m_dst->AsPropertySymOpnd();
  2987. }
  2988. return nullptr;
  2989. }
  2990. bool Instr::CallsAccessor(IR::PropertySymOpnd* methodOpnd)
  2991. {
  2992. if (methodOpnd)
  2993. {
  2994. Assert(methodOpnd->HasObjTypeSpecFldInfo());
  2995. return methodOpnd->UsesAccessor();
  2996. }
  2997. return CallsGetter() || CallsSetter();
  2998. }
  2999. bool Instr::CallsSetter(IR::PropertySymOpnd* methodOpnd)
  3000. {
  3001. return
  3002. this->IsProfiledInstr() &&
  3003. (this->m_dst && this->m_dst->IsSymOpnd() && this->m_dst->AsSymOpnd()->IsPropertySymOpnd()) &&
  3004. ((this->AsProfiledInstr()->u.FldInfo().flags & Js::FldInfo_FromAccessor) != 0);
  3005. }
  3006. bool Instr::CallsGetter(IR::PropertySymOpnd* methodOpnd)
  3007. {
  3008. return
  3009. this->IsProfiledInstr() &&
  3010. (this->m_src1 && this->m_src1->IsSymOpnd() && this->m_src1->AsSymOpnd()->IsPropertySymOpnd()) &&
  3011. ((this->AsProfiledInstr()->u.FldInfo().flags & Js::FldInfo_FromAccessor) != 0);
  3012. }
  3013. IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, ValueType type, Func* func, Js::Var varLocal/* = nullptr*/)
  3014. {
  3015. IR::Opnd *srcOpnd = nullptr;
  3016. IR::Instr *instr;
  3017. if (Js::TaggedInt::Is(varConst))
  3018. {
  3019. IntConstType value = Js::TaggedInt::ToInt32((Js::Var)varConst);
  3020. instr = IR::Instr::New(Js::OpCode::LdC_A_I4, dstOpnd, IR::IntConstOpnd::New(value, TyInt32, func), func);
  3021. if (dstOpnd->m_sym->IsSingleDef())
  3022. {
  3023. dstOpnd->m_sym->SetIsIntConst(value);
  3024. }
  3025. }
  3026. else
  3027. {
  3028. if (varConst == func->GetThreadContextInfo()->GetNullFrameDisplayAddr())
  3029. {
  3030. instr = IR::Instr::New(
  3031. Js::OpCode::Ld_A,
  3032. dstOpnd,
  3033. IR::AddrOpnd::New(
  3034. func->GetThreadContextInfo()->GetNullFrameDisplayAddr(),
  3035. IR::AddrOpndKindDynamicMisc,
  3036. func),
  3037. func);
  3038. }
  3039. else if (varConst == func->GetThreadContextInfo()->GetStrictNullFrameDisplayAddr())
  3040. {
  3041. instr = IR::Instr::New(
  3042. Js::OpCode::Ld_A,
  3043. dstOpnd,
  3044. IR::AddrOpnd::New(
  3045. func->GetThreadContextInfo()->GetStrictNullFrameDisplayAddr(),
  3046. IR::AddrOpndKindDynamicMisc,
  3047. func),
  3048. func);
  3049. }
  3050. else
  3051. {
  3052. ValueType valueType;
  3053. if(type.IsString())
  3054. {
  3055. srcOpnd = IR::AddrOpnd::New(varConst, IR::AddrOpndKindDynamicVar, func, true, varLocal);
  3056. instr = IR::Instr::New(Js::OpCode::LdStr, dstOpnd, srcOpnd, func);
  3057. Assert(dstOpnd->m_sym->m_isSingleDef);
  3058. if (dstOpnd->m_sym->IsSingleDef())
  3059. {
  3060. dstOpnd->m_sym->m_isStrConst = true;
  3061. dstOpnd->m_sym->m_isConst = true;
  3062. }
  3063. dstOpnd->SetValueType(ValueType::String);
  3064. srcOpnd->SetValueType(ValueType::String);
  3065. }
  3066. else if(type.IsNumber())
  3067. {
  3068. // TODO (michhol): OOP JIT. we may need to unbox before sending over const table
  3069. if (!func->IsOOPJIT())
  3070. {
  3071. srcOpnd = IR::FloatConstOpnd::New((Js::Var)varConst, TyFloat64, func);
  3072. }
  3073. else
  3074. {
  3075. srcOpnd = IR::FloatConstOpnd::New((Js::Var)varConst, TyFloat64, func
  3076. #if !FLOATVAR
  3077. ,varLocal
  3078. #endif
  3079. );
  3080. }
  3081. instr = IR::Instr::New(Js::OpCode::LdC_A_R8, dstOpnd, srcOpnd, func);
  3082. if (dstOpnd->m_sym->IsSingleDef())
  3083. {
  3084. dstOpnd->m_sym->SetIsFloatConst();
  3085. #if FLOATVAR
  3086. dstOpnd->m_sym->m_isNotInt = FALSE;
  3087. #else
  3088. // Don't set m_isNotInt to true if the float constant value is an int32 or uint32. Uint32s may sometimes be
  3089. // treated as int32s for the purposes of int specialization.
  3090. dstOpnd->m_sym->m_isNotInt = !Js::JavascriptNumber::IsInt32OrUInt32(((IR::FloatConstOpnd*)srcOpnd)->m_value);
  3091. #endif
  3092. }
  3093. }
  3094. else
  3095. {
  3096. if (type.IsUndefined() || type.IsNull() || type.IsBoolean())
  3097. {
  3098. valueType = type;
  3099. }
  3100. else
  3101. {
  3102. valueType = ValueType::GetObject(ObjectType::Object);
  3103. }
  3104. srcOpnd = IR::AddrOpnd::New(varConst, IR::AddrOpndKindDynamicVar, func, true, varLocal);
  3105. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, func);
  3106. if (dstOpnd->m_sym->IsSingleDef())
  3107. {
  3108. dstOpnd->m_sym->m_isConst = true;
  3109. }
  3110. dstOpnd->SetValueType(valueType);
  3111. srcOpnd->SetValueType(valueType);
  3112. }
  3113. }
  3114. }
  3115. return instr;
  3116. }
  3117. bool Instr::UsesAllFields()
  3118. {
  3119. return OpCodeAttr::UseAllFields(this->m_opcode) || this->CallsAccessor();
  3120. }
  3121. BranchInstr *
  3122. Instr::ChangeCmCCToBranchInstr(LabelInstr *targetInstr)
  3123. {
  3124. Js::OpCode newOpcode;
  3125. switch (this->m_opcode)
  3126. {
  3127. case Js::OpCode::CmEq_A:
  3128. newOpcode = Js::OpCode::BrEq_A;
  3129. break;
  3130. case Js::OpCode::CmGe_A:
  3131. newOpcode = Js::OpCode::BrGe_A;
  3132. break;
  3133. case Js::OpCode::CmGt_A:
  3134. newOpcode = Js::OpCode::BrGt_A;
  3135. break;
  3136. case Js::OpCode::CmLt_A:
  3137. newOpcode = Js::OpCode::BrLt_A;
  3138. break;
  3139. case Js::OpCode::CmLe_A:
  3140. newOpcode = Js::OpCode::BrLe_A;
  3141. break;
  3142. case Js::OpCode::CmUnGe_A:
  3143. newOpcode = Js::OpCode::BrUnGe_A;
  3144. break;
  3145. case Js::OpCode::CmUnGt_A:
  3146. newOpcode = Js::OpCode::BrUnGt_A;
  3147. break;
  3148. case Js::OpCode::CmUnLt_A:
  3149. newOpcode = Js::OpCode::BrUnLt_A;
  3150. break;
  3151. case Js::OpCode::CmUnLe_A:
  3152. newOpcode = Js::OpCode::BrUnLe_A;
  3153. break;
  3154. case Js::OpCode::CmNeq_A:
  3155. newOpcode = Js::OpCode::BrNeq_A;
  3156. break;
  3157. case Js::OpCode::CmSrEq_A:
  3158. newOpcode = Js::OpCode::BrSrEq_A;
  3159. break;
  3160. case Js::OpCode::CmSrNeq_A:
  3161. newOpcode = Js::OpCode::BrSrNeq_A;
  3162. break;
  3163. case Js::OpCode::CmEq_I4:
  3164. newOpcode = Js::OpCode::BrEq_I4;
  3165. break;
  3166. case Js::OpCode::CmGe_I4:
  3167. newOpcode = Js::OpCode::BrGe_I4;
  3168. break;
  3169. case Js::OpCode::CmGt_I4:
  3170. newOpcode = Js::OpCode::BrGt_I4;
  3171. break;
  3172. case Js::OpCode::CmLt_I4:
  3173. newOpcode = Js::OpCode::BrLt_I4;
  3174. break;
  3175. case Js::OpCode::CmLe_I4:
  3176. newOpcode = Js::OpCode::BrLe_I4;
  3177. break;
  3178. case Js::OpCode::CmUnGe_I4:
  3179. newOpcode = Js::OpCode::BrUnGe_I4;
  3180. break;
  3181. case Js::OpCode::CmUnGt_I4:
  3182. newOpcode = Js::OpCode::BrUnGt_I4;
  3183. break;
  3184. case Js::OpCode::CmUnLt_I4:
  3185. newOpcode = Js::OpCode::BrUnLt_I4;
  3186. break;
  3187. case Js::OpCode::CmUnLe_I4:
  3188. newOpcode = Js::OpCode::BrUnLe_I4;
  3189. break;
  3190. case Js::OpCode::CmNeq_I4:
  3191. newOpcode = Js::OpCode::BrNeq_I4;
  3192. break;
  3193. default:
  3194. Assert(UNREACHED);
  3195. __assume(UNREACHED);
  3196. }
  3197. BranchInstr *instrBr = BranchInstr::New(newOpcode, targetInstr, this->m_func);
  3198. this->InsertBefore(instrBr);
  3199. instrBr->SetByteCodeOffset(this);
  3200. instrBr->SetSrc1(this->UnlinkSrc1());
  3201. instrBr->SetSrc2(this->UnlinkSrc2());
  3202. this->Remove();
  3203. return instrBr;
  3204. }
  3205. bool Instr::IsCmCC_A()
  3206. {
  3207. return (this->m_opcode >= Js::OpCode::CmEq_A && this->m_opcode <= Js::OpCode::CmSrNeq_A) && this->GetSrc1()->IsVar();
  3208. }
  3209. bool Instr::IsCmCC_R8()
  3210. {
  3211. return (this->m_opcode >= Js::OpCode::CmEq_A && this->m_opcode <= Js::OpCode::CmSrNeq_A) && this->GetSrc1()->IsFloat64();
  3212. }
  3213. bool Instr::IsCmCC_I4()
  3214. {
  3215. return (this->m_opcode >= Js::OpCode::CmEq_I4 && this->m_opcode <= Js::OpCode::CmUnGe_I4);
  3216. }
  3217. bool Instr::BinaryCalculator(IntConstType src1Const, IntConstType src2Const, IntConstType *pResult)
  3218. {
  3219. IntConstType value = 0;
  3220. switch (this->m_opcode)
  3221. {
  3222. case Js::OpCode::Add_A:
  3223. if (IntConstMath::Add(src1Const, src2Const, &value))
  3224. {
  3225. return false;
  3226. }
  3227. break;
  3228. case Js::OpCode::Sub_A:
  3229. if (IntConstMath::Sub(src1Const, src2Const, &value))
  3230. {
  3231. return false;
  3232. }
  3233. break;
  3234. case Js::OpCode::Mul_A:
  3235. if (IntConstMath::Mul(src1Const, src2Const, &value))
  3236. {
  3237. return false;
  3238. }
  3239. if (value == 0)
  3240. {
  3241. // might be -0
  3242. // Bail for now...
  3243. return false;
  3244. }
  3245. break;
  3246. case Js::OpCode::Div_A:
  3247. if (src2Const == 0)
  3248. {
  3249. // Could fold to INF/-INF
  3250. // instr->HoistSrc1(Js::OpCode::Ld_A);
  3251. return false;
  3252. }
  3253. if (src1Const == 0 && src2Const < 0)
  3254. {
  3255. // folds to -0. Bail for now...
  3256. return false;
  3257. }
  3258. if (IntConstMath::Div(src1Const, src2Const, &value))
  3259. {
  3260. return false;
  3261. }
  3262. if (src1Const % src2Const != 0)
  3263. {
  3264. // Bail for now...
  3265. return false;
  3266. }
  3267. break;
  3268. case Js::OpCode::Rem_A:
  3269. if (src2Const == 0)
  3270. {
  3271. // Bail for now...
  3272. return false;
  3273. }
  3274. if (IntConstMath::Mod(src1Const, src2Const, &value))
  3275. {
  3276. return false;
  3277. }
  3278. if (value == 0)
  3279. {
  3280. // might be -0
  3281. // Bail for now...
  3282. return false;
  3283. }
  3284. break;
  3285. case Js::OpCode::Shl_A:
  3286. // We don't care about overflow here
  3287. IntConstMath::Shl(src1Const, src2Const & 0x1F, &value);
  3288. break;
  3289. case Js::OpCode::Shr_A:
  3290. // We don't care about overflow here, and there shouldn't be any
  3291. IntConstMath::Shr(src1Const, src2Const & 0x1F, &value);
  3292. break;
  3293. case Js::OpCode::ShrU_A:
  3294. // We don't care about overflow here, and there shouldn't be any
  3295. IntConstMath::ShrU(src1Const, src2Const & 0x1F, &value);
  3296. if (value < 0)
  3297. {
  3298. // ShrU produces a UInt32. If it doesn't fit in an Int32, bail as we don't
  3299. // track signs of int values.
  3300. return false;
  3301. }
  3302. break;
  3303. case Js::OpCode::And_A:
  3304. // We don't care about overflow here, and there shouldn't be any
  3305. IntConstMath::And(src1Const, src2Const, &value);
  3306. break;
  3307. case Js::OpCode::Or_A:
  3308. // We don't care about overflow here, and there shouldn't be any
  3309. IntConstMath::Or(src1Const, src2Const, &value);
  3310. break;
  3311. case Js::OpCode::Xor_A:
  3312. // We don't care about overflow here, and there shouldn't be any
  3313. IntConstMath::Xor(src1Const, src2Const, &value);
  3314. break;
  3315. case Js::OpCode::InlineMathMin:
  3316. value = src1Const < src2Const ? src1Const : src2Const;
  3317. break;
  3318. case Js::OpCode::InlineMathMax:
  3319. value = src1Const > src2Const ? src1Const : src2Const;
  3320. break;
  3321. default:
  3322. return false;
  3323. }
  3324. *pResult = value;
  3325. return true;
  3326. }
  3327. bool Instr::UnaryCalculator(IntConstType src1Const, IntConstType *pResult)
  3328. {
  3329. IntConstType value = 0;
  3330. switch (this->m_opcode)
  3331. {
  3332. case Js::OpCode::Neg_A:
  3333. if (src1Const == 0)
  3334. {
  3335. // Could fold to -0.0
  3336. return false;
  3337. }
  3338. if (IntConstMath::Neg(src1Const, &value))
  3339. {
  3340. return false;
  3341. }
  3342. break;
  3343. case Js::OpCode::Not_A:
  3344. IntConstMath::Not(src1Const, &value);
  3345. break;
  3346. case Js::OpCode::Ld_A:
  3347. if (this->HasBailOutInfo())
  3348. {
  3349. Assert(this->GetBailOutKind() == IR::BailOutExpectingInteger);
  3350. this->ClearBailOutInfo();
  3351. }
  3352. value = src1Const;
  3353. break;
  3354. case Js::OpCode::Conv_Num:
  3355. case Js::OpCode::Ld_I4:
  3356. value = src1Const;
  3357. break;
  3358. case Js::OpCode::Incr_A:
  3359. if (IntConstMath::Inc(src1Const, &value))
  3360. {
  3361. return false;
  3362. }
  3363. break;
  3364. case Js::OpCode::Decr_A:
  3365. if (IntConstMath::Dec(src1Const, &value))
  3366. {
  3367. return false;
  3368. }
  3369. break;
  3370. case Js::OpCode::InlineMathAbs:
  3371. if (src1Const == IntConstMin)
  3372. {
  3373. return false;
  3374. }
  3375. else
  3376. {
  3377. value = src1Const < 0 ? -src1Const : src1Const;
  3378. }
  3379. break;
  3380. case Js::OpCode::InlineMathClz:
  3381. DWORD clz;
  3382. DWORD src1Const32;
  3383. src1Const32 = (DWORD)src1Const;
  3384. if (_BitScanReverse(&clz, src1Const32))
  3385. {
  3386. value = 31 - clz;
  3387. }
  3388. else
  3389. {
  3390. value = 32;
  3391. }
  3392. this->ClearBailOutInfo();
  3393. break;
  3394. case Js::OpCode::InlineMathFloor:
  3395. value = src1Const;
  3396. this->ClearBailOutInfo();
  3397. break;
  3398. case Js::OpCode::InlineMathCeil:
  3399. value = src1Const;
  3400. this->ClearBailOutInfo();
  3401. break;
  3402. case Js::OpCode::InlineMathRound:
  3403. value = src1Const;
  3404. this->ClearBailOutInfo();
  3405. break;
  3406. case Js::OpCode::ToVar:
  3407. if (Js::TaggedInt::IsOverflow(src1Const))
  3408. {
  3409. return false;
  3410. }
  3411. else
  3412. {
  3413. value = src1Const;
  3414. this->ClearBailOutInfo();
  3415. break;
  3416. }
  3417. default:
  3418. return false;
  3419. }
  3420. *pResult = value;
  3421. return true;
  3422. }
  3423. #if ENABLE_DEBUG_CONFIG_OPTIONS
  3424. ///----------------------------------------------------------------------------
  3425. ///
  3426. /// Instr::DumpTestTrace
  3427. ///
  3428. /// Dump this instr in TestTrace.
  3429. ///
  3430. ///----------------------------------------------------------------------------
  3431. void
  3432. Instr::DumpTestTrace()
  3433. {
  3434. Output::Print(_u("opcode: %s "), Js::OpCodeUtil::GetOpCodeName(m_opcode));
  3435. SymOpnd * symOpnd;
  3436. if (this->m_opcode == Js::OpCode::NewScFunc || this->m_opcode == Js::OpCode::NewScGenFunc)
  3437. {
  3438. Output::Print(_u("\n"));
  3439. return;
  3440. }
  3441. Opnd * src1 = this->GetSrc1();
  3442. if (!src1)
  3443. {
  3444. Output::Print(_u("\n"));
  3445. return;
  3446. }
  3447. if (src1->GetKind() != OpndKindSym)
  3448. {
  3449. Output::Print(_u("\n"));
  3450. return;
  3451. }
  3452. symOpnd = src1->AsSymOpnd();
  3453. if (symOpnd->m_sym->IsPropertySym())
  3454. {
  3455. PropertySym *propertySym = symOpnd->m_sym->AsPropertySym();
  3456. switch (propertySym->m_fieldKind)
  3457. {
  3458. case PropertyKindData:
  3459. if (!JITManager::GetJITManager()->IsOOPJITEnabled())
  3460. {
  3461. Js::PropertyRecord const* fieldName = propertySym->GetFunc()->GetInProcThreadContext()->GetPropertyRecord(propertySym->m_propertyId);
  3462. Output::Print(_u("field: %s "), fieldName->GetBuffer());
  3463. break;
  3464. }
  3465. // else fall through
  3466. case PropertyKindSlots:
  3467. Output::Print(_u("field: [%d] "), propertySym->m_propertyId);
  3468. break;
  3469. case PropertyKindLocalSlots:
  3470. Output::Print(_u("field: l[%d] "), propertySym->m_propertyId);
  3471. break;
  3472. default:
  3473. break;
  3474. }
  3475. Output::Print(_u("\n"));
  3476. }
  3477. }
  3478. ///----------------------------------------------------------------------------
  3479. ///
  3480. /// Instr::DumpFieldCopyPropTestTrace
  3481. ///
  3482. /// Dump fieldcopyprop when testtrace is enabled.
  3483. ///
  3484. ///----------------------------------------------------------------------------
  3485. void
  3486. Instr::DumpFieldCopyPropTestTrace()
  3487. {
  3488. switch (m_opcode)
  3489. {
  3490. case Js::OpCode::LdSlot:
  3491. case Js::OpCode::LdSlotArr:
  3492. case Js::OpCode::LdFld:
  3493. case Js::OpCode::LdFldForTypeOf:
  3494. case Js::OpCode::LdRootFld:
  3495. case Js::OpCode::LdRootFldForTypeOf:
  3496. case Js::OpCode::LdMethodFld:
  3497. case Js::OpCode::LdRootMethodFld:
  3498. case Js::OpCode::LdMethodFromFlags:
  3499. case Js::OpCode::ScopedLdMethodFld:
  3500. case Js::OpCode::TypeofElem:
  3501. char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  3502. Output::Print(_u("TestTrace fieldcopyprop: function %s (%s) "),
  3503. this->m_func->GetJITFunctionBody()->GetDisplayName(),
  3504. this->m_func->GetDebugNumberSet(debugStringBuffer));
  3505. if (this->IsInlined())
  3506. {
  3507. Output::Print(_u("inlined caller function %s (%s) "),
  3508. this->m_func->GetTopFunc()->GetJITFunctionBody()->GetDisplayName(),
  3509. this->m_func->GetTopFunc()->GetDebugNumberSet(debugStringBuffer));
  3510. }
  3511. this->DumpTestTrace();
  3512. default:
  3513. break;
  3514. }
  3515. }
  3516. #endif
  3517. #if ENABLE_DEBUG_CONFIG_OPTIONS
  3518. const char *
  3519. Instr::GetBailOutKindName() const
  3520. {
  3521. IR::BailOutKind kind = (IR::BailOutKind)0;
  3522. if (this->HasBailOutInfo())
  3523. {
  3524. kind |= this->GetBailOutKind();
  3525. }
  3526. if (this->HasAuxBailOut())
  3527. {
  3528. kind |= this->GetAuxBailOutKind();
  3529. }
  3530. return ::GetBailOutKindName(kind);
  3531. }
  3532. #endif
  3533. //
  3534. // Debug dumpers
  3535. //
  3536. #if DBG_DUMP
  3537. void
  3538. Instr::DumpByteCodeOffset()
  3539. {
  3540. if (m_func->HasByteCodeOffset())
  3541. {
  3542. Output::SkipToColumn(78);
  3543. Output::Print(_u("#"));
  3544. if (this->m_number != Js::Constants::NoByteCodeOffset)
  3545. {
  3546. Output::Print(_u("%04x"), this->m_number);
  3547. Output::Print(this->IsCloned()? _u("*") : _u(" "));
  3548. }
  3549. }
  3550. if (!this->m_func->IsTopFunc())
  3551. {
  3552. Output::SkipToColumn(78);
  3553. char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  3554. Output::Print(_u(" Func #%s"), this->m_func->GetDebugNumberSet(debugStringBuffer));
  3555. }
  3556. #ifdef BAILOUT_INJECTION
  3557. if (this->bailOutByteCodeLocation != (uint)-1)
  3558. {
  3559. Output::SkipToColumn(85);
  3560. Output::Print(_u("@%4d"), this->bailOutByteCodeLocation);
  3561. }
  3562. #endif
  3563. if (this->m_opcode == Js::OpCode::InlineeStart)
  3564. {
  3565. Output::Print(_u(" %s"), this->m_func->GetJITFunctionBody()->GetDisplayName());
  3566. }
  3567. }
  3568. void
  3569. Instr::DumpGlobOptInstrString()
  3570. {
  3571. if(this->globOptInstrString)
  3572. {
  3573. Output::Print(_u("\n\n GLOBOPT INSTR: %s\n\n"), this->globOptInstrString);
  3574. }
  3575. }
  3576. ///----------------------------------------------------------------------------
  3577. ///
  3578. /// Instr::Dump
  3579. ///
  3580. /// Dump this instr.
  3581. ///
  3582. ///----------------------------------------------------------------------------
  3583. void
  3584. Instr::Dump(IRDumpFlags flags)
  3585. {
  3586. bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
  3587. bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
  3588. bool const SkipByteCodeOffset = !!(flags & IRDumpFlags_SkipByteCodeOffset);
  3589. const auto PrintOpCodeName = [&]() {
  3590. Output::SkipToColumn(23);
  3591. Output::Print(_u("%s "), Js::OpCodeUtil::GetOpCodeName(m_opcode));
  3592. Output::SkipToColumn(38);
  3593. };
  3594. // forward decl before goto statement
  3595. Opnd * dst = nullptr;
  3596. if(m_opcode == Js::OpCode::BoundCheck || m_opcode == Js::OpCode::UnsignedBoundCheck)
  3597. {
  3598. PrintOpCodeName();
  3599. // src1 <= src2 + dst
  3600. Assert(GetSrc1());
  3601. if(GetSrc1()->IsIntConstOpnd())
  3602. {
  3603. Output::Print(_u("%d"), GetSrc1()->AsIntConstOpnd()->GetValue());
  3604. }
  3605. else
  3606. {
  3607. GetSrc1()->Dump(flags, m_func);
  3608. }
  3609. bool useLessThanOrEqual = true;
  3610. bool usePlus = true;
  3611. bool dumpSrc2 = false;
  3612. int32 offset = GetDst() ? GetDst()->AsIntConstOpnd()->AsInt32() : 0;
  3613. if(GetSrc2())
  3614. {
  3615. if(GetSrc2()->IsIntConstOpnd())
  3616. {
  3617. #if DBG
  3618. int32 temp;
  3619. Assert(!Int32Math::Add(offset, GetSrc2()->AsIntConstOpnd()->AsInt32(), &temp));
  3620. #endif
  3621. offset += GetSrc2()->AsIntConstOpnd()->AsInt32();
  3622. }
  3623. else
  3624. {
  3625. dumpSrc2 = true;
  3626. if(offset == -1)
  3627. {
  3628. useLessThanOrEqual = false; // < instead of <=
  3629. offset = 0;
  3630. }
  3631. else if(offset < 0 && offset != IntConstMin)
  3632. {
  3633. usePlus = false;
  3634. offset = -offset;
  3635. }
  3636. }
  3637. }
  3638. Output::Print(_u(" %S "), useLessThanOrEqual ? "<=" : "<");
  3639. if(dumpSrc2)
  3640. {
  3641. GetSrc2()->Dump(flags, m_func);
  3642. }
  3643. if(offset != 0)
  3644. {
  3645. if(dumpSrc2)
  3646. {
  3647. Output::Print(_u(" %C "), usePlus ? '+' : '-');
  3648. }
  3649. Output::Print(_u("%d"), offset);
  3650. }
  3651. goto PrintByteCodeOffsetEtc;
  3652. }
  3653. Output::SkipToColumn(4);
  3654. dst = this->GetDst();
  3655. if (dst)
  3656. {
  3657. dst->Dump(flags, this->m_func);
  3658. bool const dumpMarkTemp = PHASE_DUMP(Js::MarkTempPhase, m_func)
  3659. || PHASE_TRACE(Js::MarkTempPhase, m_func);
  3660. bool const dumpMarkTempNumber = dumpMarkTemp || PHASE_DUMP(Js::MarkTempNumberPhase, m_func)
  3661. || PHASE_TRACE(Js::MarkTempNumberPhase, m_func);
  3662. bool const dumpMarkTempObject = dumpMarkTemp || PHASE_DUMP(Js::MarkTempObjectPhase, m_func)
  3663. || PHASE_TRACE(Js::MarkTempObjectPhase, m_func);
  3664. if ((dumpMarkTempNumber && (this->dstIsTempNumberTransferred || this->dstIsTempNumber))
  3665. || (dumpMarkTempObject && this->dstIsTempObject))
  3666. {
  3667. Output::Print(_u("["));
  3668. if (dumpMarkTempNumber)
  3669. {
  3670. if (Js::Configuration::Global.flags.Verbose || OpCodeAttr::TempNumberProducing(this->m_opcode))
  3671. {
  3672. if (this->dstIsTempNumberTransferred)
  3673. {
  3674. Assert(this->dstIsTempNumber);
  3675. Output::Print(_u("x"));
  3676. }
  3677. else if (this->dstIsTempNumber)
  3678. {
  3679. Output::Print(_u("#"));
  3680. }
  3681. }
  3682. }
  3683. if (dumpMarkTempObject)
  3684. {
  3685. if (Js::Configuration::Global.flags.Verbose || OpCodeAttr::TempObjectProducing(this->m_opcode))
  3686. {
  3687. if (this->dstIsTempObject)
  3688. {
  3689. Output::Print(_u("o"));
  3690. }
  3691. }
  3692. }
  3693. Output::Print(_u("tmp]"));
  3694. }
  3695. if(PHASE_DUMP(Js::TrackNegativeZeroPhase, m_func->GetTopFunc()) && !ShouldCheckForNegativeZero())
  3696. {
  3697. Output::Print(_u("[-0]"));
  3698. }
  3699. if (PHASE_DUMP(Js::TypedArrayVirtualPhase, m_func->GetTopFunc()) && (!IsDstNotAlwaysConvertedToInt32() || !IsDstNotAlwaysConvertedToNumber()))
  3700. {
  3701. if (!IsDstNotAlwaysConvertedToInt32())
  3702. Output::Print(_u("[->i]"));
  3703. else
  3704. Output::Print(_u("[->n]"));
  3705. }
  3706. if(PHASE_DUMP(Js::TrackIntOverflowPhase, m_func->GetTopFunc()))
  3707. {
  3708. // ignoring 32-bit overflow ?
  3709. if(!ShouldCheckFor32BitOverflow())
  3710. {
  3711. // ignoring 32-bits or more ?
  3712. if(ShouldCheckForNon32BitOverflow())
  3713. Output::Print(_u("[OF %d]"), ignoreOverflowBitCount);
  3714. else
  3715. Output::Print(_u("[OF]"));
  3716. }
  3717. }
  3718. Output::SkipToColumn(20);
  3719. Output::Print(_u("="));
  3720. }
  3721. PrintOpCodeName();
  3722. if (this->IsBranchInstr())
  3723. {
  3724. BranchInstr * branchInstr = this->AsBranchInstr();
  3725. LabelInstr * targetInstr = branchInstr->GetTarget();
  3726. bool labelPrinted = true;
  3727. if (targetInstr == NULL)
  3728. {
  3729. // Checking the 'm_isMultiBranch' field here directly as well to bypass asserting when tracing IR builder
  3730. if(branchInstr->m_isMultiBranch && branchInstr->IsMultiBranch())
  3731. {
  3732. IR::MultiBranchInstr * multiBranchInstr = branchInstr->AsMultiBrInstr();
  3733. // If this MultiBranchInstr has been lowered to a machine instruction, which means
  3734. // its opcode is not Js::OpCode::MultiBr, there is no need to print the labels.
  3735. if (this->m_opcode == Js::OpCode::MultiBr)
  3736. {
  3737. multiBranchInstr->MapMultiBrLabels([](IR::LabelInstr * labelInstr) -> void
  3738. {
  3739. Output::Print(_u("$L%d "), labelInstr->m_id);
  3740. });
  3741. }
  3742. else
  3743. {
  3744. labelPrinted = false;
  3745. }
  3746. }
  3747. else
  3748. {
  3749. Output::Print(_u("??"));
  3750. }
  3751. }
  3752. else
  3753. {
  3754. Output::Print(_u("$L%d"), targetInstr->m_id);
  3755. }
  3756. if (this->GetSrc1() && labelPrinted)
  3757. {
  3758. Output::Print(_u(", "));
  3759. }
  3760. }
  3761. else if (this->IsPragmaInstr() && this->m_opcode == Js::OpCode::StatementBoundary)
  3762. {
  3763. Output::Print(_u("#%d"), this->AsPragmaInstr()->m_statementIndex);
  3764. }
  3765. // scope
  3766. {
  3767. Opnd * src1 = this->GetSrc1();
  3768. if (this->m_opcode == Js::OpCode::NewScFunc || this->m_opcode == Js::OpCode::NewScGenFunc)
  3769. {
  3770. Assert(src1->IsIntConstOpnd());
  3771. Js::ParseableFunctionInfo * function = nullptr;
  3772. if (!m_func->IsOOPJIT())
  3773. {
  3774. function = ((Js::ParseableFunctionInfo *)m_func->GetJITFunctionBody()->GetAddr())->GetNestedFunctionForExecution((uint)src1->AsIntConstOpnd()->GetValue())->GetParseableFunctionInfo();
  3775. }
  3776. Output::Print(_u("func:%s()"), function ? function->GetDisplayName() : _u("???"));
  3777. Output::Print(_u(", env:"));
  3778. this->GetSrc2()->AsRegOpnd()->m_sym->Dump(flags);
  3779. }
  3780. else if (src1)
  3781. {
  3782. src1->Dump(flags, this->m_func);
  3783. Opnd * src2 = this->GetSrc2();
  3784. if (src2)
  3785. {
  3786. Output::Print(_u(", "));
  3787. src2->Dump(flags, this->m_func);
  3788. }
  3789. }
  3790. }
  3791. if (this->IsByteCodeUsesInstr())
  3792. {
  3793. if (this->AsByteCodeUsesInstr()->GetByteCodeUpwardExposedUsed())
  3794. {
  3795. bool first = true;
  3796. FOREACH_BITSET_IN_SPARSEBV(id, this->AsByteCodeUsesInstr()->GetByteCodeUpwardExposedUsed())
  3797. {
  3798. Output::Print(first? _u("s%d") : _u(", s%d"), id);
  3799. first = false;
  3800. }
  3801. NEXT_BITSET_IN_SPARSEBV;
  3802. }
  3803. if (this->AsByteCodeUsesInstr()->propertySymUse)
  3804. {
  3805. Output::Print(_u(" PropSym: %d"), this->AsByteCodeUsesInstr()->propertySymUse->m_id);
  3806. }
  3807. }
  3808. PrintByteCodeOffsetEtc:
  3809. if (!AsmDumpMode && !SkipByteCodeOffset)
  3810. {
  3811. this->DumpByteCodeOffset();
  3812. }
  3813. if (!SimpleForm)
  3814. {
  3815. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  3816. {
  3817. BailOutInfo * bailOutInfo = this->GetBailOutInfo();
  3818. Output::SkipToColumn(85);
  3819. if (!AsmDumpMode)
  3820. {
  3821. Output::Print(_u("Bailout: #%04x"), bailOutInfo->bailOutOffset);
  3822. }
  3823. if (!bailOutInfo->bailOutFunc->IsTopFunc())
  3824. {
  3825. char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  3826. Output::Print(_u(" Func %s"), bailOutInfo->bailOutFunc->GetDebugNumberSet(debugStringBuffer));
  3827. }
  3828. Output::Print(_u(" (%S)"), this->GetBailOutKindName());
  3829. }
  3830. }
  3831. if ((flags & IRDumpFlags_SkipEndLine) == 0)
  3832. {
  3833. Output::Print(_u("\n"));
  3834. }
  3835. }
  3836. ///----------------------------------------------------------------------------
  3837. ///
  3838. /// LabelInstr::Dump
  3839. ///
  3840. /// Dump this label.
  3841. ///
  3842. ///----------------------------------------------------------------------------
  3843. void
  3844. LabelInstr::Dump(IRDumpFlags flags)
  3845. {
  3846. if (this->m_block != NULL)
  3847. {
  3848. this->m_block->DumpHeader();
  3849. }
  3850. Output::Print(_u("$L%d:"), this->m_id);
  3851. if (this->isOpHelper)
  3852. {
  3853. Output::Print(_u(" [helper]"));
  3854. }
  3855. if (this->m_isLoopTop)
  3856. {
  3857. Output::Print(_u(" >>>>>>>>>>>>> LOOP TOP >>>>>>>>>>>>>"));
  3858. }
  3859. if (this->IsProfiledLabelInstr())
  3860. {
  3861. Output::SkipToColumn(50);
  3862. switch (this->AsProfiledLabelInstr()->loopImplicitCallFlags)
  3863. {
  3864. case Js::ImplicitCall_HasNoInfo:
  3865. Output::Print(_u("Implicit call: ???"));
  3866. break;
  3867. case Js::ImplicitCall_None:
  3868. Output::Print(_u("Implicit call: no"));
  3869. break;
  3870. default:
  3871. Output::Print(_u("Implicit call: yes"));
  3872. break;
  3873. }
  3874. }
  3875. if ((flags & (IRDumpFlags_AsmDumpMode | IRDumpFlags_SkipByteCodeOffset)) == 0)
  3876. {
  3877. this->DumpByteCodeOffset();
  3878. }
  3879. Output::Print(_u("\n"));
  3880. }
  3881. void
  3882. PragmaInstr::Dump(IRDumpFlags flags)
  3883. {
  3884. if (Js::Configuration::Global.flags.PrintSrcInDump && this->m_opcode == Js::OpCode::StatementBoundary)
  3885. {
  3886. Js::FunctionBody * functionBody = nullptr;
  3887. if (!m_func->IsOOPJIT())
  3888. {
  3889. functionBody = ((Js::FunctionBody*)m_func->GetJITFunctionBody()->GetAddr());
  3890. }
  3891. if (functionBody)
  3892. {
  3893. functionBody->PrintStatementSourceLine(this->m_statementIndex);
  3894. }
  3895. }
  3896. __super::Dump(flags);
  3897. }
  3898. ///----------------------------------------------------------------------------
  3899. ///
  3900. /// Instr::Dump
  3901. ///
  3902. /// Dump a window of instructions around this instr.
  3903. ///
  3904. ///----------------------------------------------------------------------------
  3905. void
  3906. Instr::Dump(int window)
  3907. {
  3908. Instr * instr;
  3909. int i;
  3910. Output::Print(_u("-------------------------------------------------------------------------------"));
  3911. if (this == NULL)
  3912. {
  3913. return;
  3914. }
  3915. for (i = 0, instr = this; (instr->m_prev != NULL && i < window/2); instr = instr->m_prev, ++i)
  3916. {} // Nothing
  3917. for (i = 0; (instr != nullptr && i < window); instr = instr->m_next, ++i)
  3918. {
  3919. if (instr == this)
  3920. {
  3921. Output::Print(_u("=>"));
  3922. }
  3923. instr->Dump();
  3924. }
  3925. }
  3926. void
  3927. Instr::Dump()
  3928. {
  3929. this->Dump(IRDumpFlags_None);
  3930. }
  3931. void
  3932. Instr::DumpSimple()
  3933. {
  3934. this->Dump(IRDumpFlags_SimpleForm);
  3935. }
  3936. char16 *
  3937. Instr::DumpString()
  3938. {
  3939. Output::CaptureStart();
  3940. this->Dump();
  3941. return Output::CaptureEnd();
  3942. }
  3943. void
  3944. Instr::DumpRange(Instr *instrEnd)
  3945. {
  3946. Output::Print(_u("-------------------------------------------------------------------------------\n"));
  3947. FOREACH_INSTR_IN_RANGE(instr, this, instrEnd)
  3948. {
  3949. instr->Dump();
  3950. }
  3951. NEXT_INSTR_IN_RANGE;
  3952. Output::Print(_u("-------------------------------------------------------------------------------\n"));
  3953. }
  3954. #endif
  3955. } // namespace IR