IR.cpp 122 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374
  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 && this->m_func->GetHasStackArgs() && topFunc->GetHasStackArgs();
  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. Js::Var
  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. Js::Var 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, fixedValue, instr->m_func);
  108. OUTPUT_VERBOSE_TRACE(Js::UseFixedDataPropsPhase,
  109. L"FixedFields: Replacing the source (fixed Data prop) with property id %s with 0x%x .\n",
  110. propSymOpnd->GetPropertySym()->GetName(), fixedValue);
  111. instr->InsertAfter(loadInstr);
  112. propSymOpnd->SetUsesFixedValue(true);
  113. return fixedValue;
  114. }
  115. }
  116. return nullptr;
  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(this && 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(Func * func)
  757. {
  758. ByteCodeUsesInstr * byteCodeUses = JitAnew(func->m_alloc, IR::ByteCodeUsesInstr);
  759. byteCodeUses->Init(Js::OpCode::ByteCodeUses, InstrKindByteCodeUses, func);
  760. byteCodeUses->byteCodeUpwardExposedUsed = nullptr;
  761. byteCodeUses->propertySymUse = nullptr;
  762. return byteCodeUses;
  763. }
  764. ByteCodeUsesInstr *
  765. ByteCodeUsesInstr::New(IR::Instr* originalBytecodeInstr, SymID symid)
  766. {
  767. Func* func = originalBytecodeInstr->m_func;
  768. ByteCodeUsesInstr * byteCodeUses = JitAnew(func->m_alloc, IR::ByteCodeUsesInstr);
  769. byteCodeUses->Init(Js::OpCode::ByteCodeUses, InstrKindByteCodeUses, func);
  770. byteCodeUses->byteCodeUpwardExposedUsed = JitAnew(func->m_alloc, BVSparse<JitArenaAllocator>, func->m_alloc);
  771. byteCodeUses->byteCodeUpwardExposedUsed->Set(symid);
  772. byteCodeUses->SetByteCodeOffset(originalBytecodeInstr);
  773. byteCodeUses->propertySymUse = nullptr;
  774. return byteCodeUses;
  775. }
  776. void ByteCodeUsesInstr::Set(uint symId)
  777. {
  778. if(!byteCodeUpwardExposedUsed)
  779. {
  780. byteCodeUpwardExposedUsed = JitAnew(m_func->m_alloc, BVSparse<JitArenaAllocator>, m_func->m_alloc);
  781. }
  782. byteCodeUpwardExposedUsed->Set(symId);
  783. }
  784. BailOutInfo *
  785. Instr::GetBailOutInfo() const
  786. {
  787. Assert(this->HasBailOutInfo() || this->HasAuxBailOut());
  788. switch (this->m_kind)
  789. {
  790. case InstrKindInstr:
  791. return ((BailOutInstr const *)this)->bailOutInfo;
  792. case InstrKindProfiled:
  793. return ((ProfiledBailOutInstr const *)this)->bailOutInfo;
  794. case InstrKindBranch:
  795. return ((BranchBailOutInstr const *)this)->bailOutInfo;
  796. default:
  797. Assert(false);
  798. __assume(false);
  799. }
  800. }
  801. BailOutKind
  802. Instr::GetBailOutKind() const
  803. {
  804. Assert(this->HasBailOutInfo());
  805. switch (this->m_kind)
  806. {
  807. case InstrKindInstr:
  808. return ((BailOutInstr const *)this)->bailOutKind;
  809. case InstrKindProfiled:
  810. return ((ProfiledBailOutInstr const *)this)->bailOutKind;
  811. case InstrKindBranch:
  812. return ((BranchBailOutInstr const *)this)->bailOutKind;
  813. default:
  814. Assert(false);
  815. return BailOutInvalid;
  816. }
  817. }
  818. BailOutKind
  819. Instr::GetBailOutKindNoBits() const
  820. {
  821. return GetBailOutKind() & ~IR::BailOutKindBits;
  822. }
  823. BailOutKind
  824. Instr::GetAuxBailOutKind() const
  825. {
  826. Assert(this->HasAuxBailOut());
  827. switch (this->m_kind)
  828. {
  829. case InstrKindInstr:
  830. return ((BailOutInstr const *)this)->auxBailOutKind;
  831. case InstrKindProfiled:
  832. return ((ProfiledBailOutInstr const *)this)->auxBailOutKind;
  833. case InstrKindBranch:
  834. return ((BranchBailOutInstr const *)this)->auxBailOutKind;
  835. default:
  836. Assert(false);
  837. return BailOutInvalid;
  838. }
  839. }
  840. void Instr::SetBailOutKind(const IR::BailOutKind bailOutKind)
  841. {
  842. Assert(this->HasBailOutInfo());
  843. Assert(bailOutKind != IR::BailOutInvalid);
  844. this->SetBailOutKind_NoAssert(bailOutKind);
  845. }
  846. // Helper to set bail out kind, doesn't assert.
  847. void Instr::SetBailOutKind_NoAssert(const IR::BailOutKind bailOutKind)
  848. {
  849. Assert(IsValidBailOutKindAndBits(bailOutKind));
  850. switch (this->m_kind)
  851. {
  852. case InstrKindInstr:
  853. ((BailOutInstr *)this)->bailOutKind = bailOutKind;
  854. break;
  855. case InstrKindProfiled:
  856. ((ProfiledBailOutInstr *)this)->bailOutKind = bailOutKind;
  857. break;
  858. case InstrKindBranch:
  859. ((BranchBailOutInstr *)this)->bailOutKind = bailOutKind;
  860. break;
  861. default:
  862. Assert(false);
  863. __assume(false);
  864. }
  865. }
  866. void Instr::SetAuxBailOutKind(const IR::BailOutKind bailOutKind)
  867. {
  868. switch (this->m_kind)
  869. {
  870. case InstrKindInstr:
  871. ((BailOutInstr *)this)->auxBailOutKind = bailOutKind;
  872. break;
  873. case InstrKindProfiled:
  874. ((ProfiledBailOutInstr *)this)->auxBailOutKind = bailOutKind;
  875. break;
  876. case InstrKindBranch:
  877. ((BranchBailOutInstr *)this)->auxBailOutKind = bailOutKind;
  878. break;
  879. default:
  880. Assert(false);
  881. __assume(false);
  882. }
  883. }
  884. BailOutInfo *
  885. Instr::UnlinkBailOutInfo()
  886. {
  887. BailOutInfo *bailOutInfo;
  888. Assert(this->HasBailOutInfo() || this->HasAuxBailOut());
  889. switch (this->m_kind)
  890. {
  891. case InstrKindInstr:
  892. bailOutInfo = ((BailOutInstr const *)this)->bailOutInfo;
  893. ((BailOutInstr *)this)->bailOutInfo = nullptr;
  894. break;
  895. case InstrKindProfiled:
  896. bailOutInfo = ((ProfiledBailOutInstr const *)this)->bailOutInfo;
  897. ((ProfiledBailOutInstr *)this)->bailOutInfo = nullptr;
  898. break;
  899. case InstrKindBranch:
  900. bailOutInfo = ((BranchBailOutInstr const *)this)->bailOutInfo;
  901. ((BranchBailOutInstr *)this)->bailOutInfo = nullptr;
  902. break;
  903. default:
  904. Assert(false);
  905. return nullptr;
  906. }
  907. Assert(bailOutInfo);
  908. #if 0
  909. if (bailOutInfo->bailOutInstr == this)
  910. {
  911. bailOutInfo->bailOutInstr = nullptr;
  912. }
  913. #endif
  914. this->hasBailOutInfo = false;
  915. this->hasAuxBailOut = false;
  916. return bailOutInfo;
  917. }
  918. void
  919. Instr::ReplaceBailOutInfo(BailOutInfo *newBailOutInfo)
  920. {
  921. BailOutInfo *oldBailOutInfo;
  922. #if DBG
  923. newBailOutInfo->wasCopied = true;
  924. #endif
  925. Assert(this->HasBailOutInfo() || this->HasAuxBailOut());
  926. switch (this->m_kind)
  927. {
  928. case InstrKindInstr:
  929. oldBailOutInfo = ((BailOutInstr *)this)->bailOutInfo;
  930. ((BailOutInstr *)this)->bailOutInfo = newBailOutInfo;
  931. break;
  932. case InstrKindProfiled:
  933. oldBailOutInfo = ((ProfiledBailOutInstr *)this)->bailOutInfo;
  934. ((ProfiledBailOutInstr *)this)->bailOutInfo = newBailOutInfo;
  935. break;
  936. case InstrKindBranch:
  937. AssertMsg(!this->HasBailOutInfo() && this->HasAuxBailOut(), "ReplaceBailOutInfo is not used with InstrKindBranch for non-aux bailout");
  938. oldBailOutInfo = ((BranchBailOutInstr *)this)->bailOutInfo;
  939. ((BranchBailOutInstr *)this)->bailOutInfo = newBailOutInfo;
  940. break;
  941. default:
  942. Assert(false);
  943. __assume(UNREACHED);
  944. }
  945. Assert(!oldBailOutInfo->wasCloned && !oldBailOutInfo->wasCopied);
  946. if (oldBailOutInfo->bailOutInstr == this)
  947. {
  948. JitArenaAllocator * alloc = this->m_func->m_alloc;
  949. oldBailOutInfo->Clear(alloc);
  950. JitAdelete(alloc, oldBailOutInfo);
  951. }
  952. }
  953. IR::Instr *Instr::ShareBailOut()
  954. {
  955. BailOutInfo *const bailOutInfo = GetBailOutInfo();
  956. bailOutInfo->bailOutInstr = nullptr;
  957. #if DBG
  958. bailOutInfo->wasCopied = true;
  959. #endif
  960. IR::Instr *const sharedBail =
  961. IR::BailOutInstr::New(Js::OpCode::BailTarget, IR::BailOutShared, bailOutInfo, bailOutInfo->bailOutFunc);
  962. sharedBail->SetByteCodeOffset(this);
  963. InsertAfter(sharedBail);
  964. Assert(bailOutInfo->bailOutInstr == sharedBail);
  965. return sharedBail;
  966. }
  967. void
  968. Instr::UnlinkStartCallFromBailOutInfo(IR::Instr *endInstr) const
  969. {
  970. #ifdef _M_IX86
  971. // The StartCall instruction is being deleted, or is being moved and may later be deleted,
  972. // so remove its references from bailouts in the given range.
  973. // This only happens during cloning, which is rare, and only across the range of instructions
  974. // that evaluate outgoing arguments, which is long only in synthetic cases.
  975. Assert(this->m_opcode == Js::OpCode::StartCall);
  976. if (!this->m_func->hasBailout)
  977. {
  978. return;
  979. }
  980. FOREACH_INSTR_IN_RANGE(instr, this->m_next, endInstr)
  981. {
  982. if (instr->HasBailOutInfo())
  983. {
  984. BailOutInfo *bailOutInfo = instr->GetBailOutInfo();
  985. bailOutInfo->UnlinkStartCall(this);
  986. }
  987. }
  988. NEXT_INSTR_IN_RANGE;
  989. #endif
  990. }
  991. Opnd *Instr::FindCallArgumentOpnd(const Js::ArgSlot argSlot, IR::Instr * *const ownerInstrRef)
  992. {
  993. Assert(OpCodeAttr::CallInstr(m_opcode));
  994. Assert(argSlot != static_cast<Js::ArgSlot>(0));
  995. IR::Instr *argInstr = this;
  996. Assert(argInstr->GetSrc2());
  997. Assert(argInstr->GetSrc2()->IsSymOpnd());
  998. do
  999. {
  1000. StackSym *const linkSym = argInstr->GetSrc2()->AsSymOpnd()->m_sym->AsStackSym();
  1001. Assert(linkSym->IsSingleDef());
  1002. Assert(linkSym->IsArgSlotSym());
  1003. argInstr = linkSym->m_instrDef;
  1004. Assert(argInstr->GetSrc2());
  1005. if(argInstr->m_opcode == Js::OpCode::ArgOut_A_InlineSpecialized)
  1006. {
  1007. // This is a fake ArgOut, skip it
  1008. continue;
  1009. }
  1010. if(linkSym->GetArgSlotNum() == argSlot)
  1011. {
  1012. if(ownerInstrRef)
  1013. {
  1014. *ownerInstrRef = argInstr;
  1015. }
  1016. return argInstr->GetSrc1();
  1017. }
  1018. } while(argInstr->GetSrc2()->IsSymOpnd());
  1019. return nullptr;
  1020. }
  1021. bool
  1022. Instr::FetchOperands(_Out_writes_(argsOpndLength) IR::Opnd **argsOpnd, uint argsOpndLength)
  1023. {
  1024. return this->ForEachCallDirectArgOutInstrBackward([&](IR::Instr *argOutInstr, uint argNum)
  1025. {
  1026. argsOpnd[argNum] = argOutInstr->GetSrc1();
  1027. return argNum == 0;
  1028. }, argsOpndLength);
  1029. }
  1030. bool Instr::ShouldCheckForNegativeZero() const
  1031. {
  1032. return !ignoreNegativeZero;
  1033. }
  1034. bool Instr::IsDstNotAlwaysConvertedToInt32() const
  1035. {
  1036. return !dstIsAlwaysConvertedToInt32;
  1037. }
  1038. bool Instr::IsDstNotAlwaysConvertedToNumber() const
  1039. {
  1040. return !dstIsAlwaysConvertedToNumber;
  1041. }
  1042. bool Instr::ShouldCheckForIntOverflow() const
  1043. {
  1044. return ShouldCheckFor32BitOverflow() || ShouldCheckForNon32BitOverflow();
  1045. }
  1046. bool Instr::ShouldCheckFor32BitOverflow() const
  1047. {
  1048. return !(ignoreIntOverflow || ignoreIntOverflowInRange);
  1049. }
  1050. bool Instr::ShouldCheckForNon32BitOverflow() const
  1051. {
  1052. return ignoreOverflowBitCount != 32;
  1053. }
  1054. template <typename InstrType> struct IRKindMap;
  1055. template <> struct IRKindMap<IR::Instr> { static const IRKind InstrKind = InstrKindInstr; };
  1056. template <> struct IRKindMap<IR::ProfiledInstr> { static const IRKind InstrKind = InstrKindProfiled; };
  1057. template <> struct IRKindMap<IR::BranchInstr> { static const IRKind InstrKind = InstrKindBranch; };
  1058. template <typename InstrType>
  1059. BailOutInstrTemplate<InstrType> *
  1060. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1061. {
  1062. Assert(func == bailOutTarget->m_func);
  1063. BailOutInfo * bailOutInfo = JitAnew(func->m_alloc, BailOutInfo, bailOutTarget->GetByteCodeOffset(), func);
  1064. #if ENABLE_DEBUG_CONFIG_OPTIONS
  1065. bailOutInfo->bailOutOpcode = opcode;
  1066. #endif
  1067. return BailOutInstrTemplate::New(opcode, kind, bailOutInfo, func);
  1068. }
  1069. template <typename InstrType>
  1070. BailOutInstrTemplate<InstrType> *
  1071. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, IR::Opnd *dst, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1072. {
  1073. BailOutInstrTemplate *instr = BailOutInstrTemplate::New(opcode, kind, bailOutTarget, func);
  1074. instr->SetDst(dst);
  1075. return instr;
  1076. }
  1077. template <typename InstrType>
  1078. BailOutInstrTemplate<InstrType> *
  1079. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, IR::Opnd *dst, IR::Opnd *src1, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1080. {
  1081. BailOutInstrTemplate *instr = BailOutInstrTemplate::New(opcode, dst, kind, bailOutTarget, func);
  1082. instr->SetSrc1(src1);
  1083. return instr;
  1084. }
  1085. template <typename InstrType>
  1086. BailOutInstrTemplate<InstrType> *
  1087. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, IR::Opnd *dst, IR::Opnd *src1, IR::Opnd *src2, BailOutKind kind, IR::Instr * bailOutTarget, Func * func)
  1088. {
  1089. BailOutInstrTemplate *instr = BailOutInstrTemplate::New(opcode, dst, src1, kind, bailOutTarget, func);
  1090. instr->SetSrc2(src2);
  1091. return instr;
  1092. }
  1093. template <typename InstrType>
  1094. BailOutInstrTemplate<InstrType> *
  1095. BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, BailOutKind kind, BailOutInfo * bailOutInfo, Func * func)
  1096. {
  1097. Assert(func == bailOutInfo->bailOutFunc);
  1098. Assert(IsValidBailOutKindAndBits(kind));
  1099. BailOutInstrTemplate * bailOutInstr = JitAnew(func->m_alloc, BailOutInstrTemplate);
  1100. bailOutInstr->Init(opcode, IRKindMap<InstrType>::InstrKind, func);
  1101. #if ENABLE_DEBUG_CONFIG_OPTIONS
  1102. bailOutInfo->bailOutOpcode = opcode;
  1103. #endif
  1104. bailOutInstr->bailOutInfo = bailOutInfo;
  1105. bailOutInstr->bailOutKind = kind;
  1106. bailOutInstr->auxBailOutKind = BailOutInvalid;
  1107. if (bailOutInfo->bailOutInstr == nullptr)
  1108. {
  1109. bailOutInfo->bailOutInstr = bailOutInstr;
  1110. }
  1111. else if (bailOutInfo->sharedBailOutKind)
  1112. {
  1113. if (bailOutInfo->bailOutInstr->HasBailOutInfo())
  1114. {
  1115. bailOutInfo->sharedBailOutKind = bailOutInfo->bailOutInstr->GetBailOutKind() == kind;
  1116. }
  1117. else
  1118. {
  1119. // 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
  1120. // share bailout in lowerer. See Instr::ShareBailOut.
  1121. bailOutInfo->sharedBailOutKind = false;
  1122. }
  1123. }
  1124. func->hasBailout = true;
  1125. // Indicate that the function has bailout instructions
  1126. // This information is used to determine whether to free jitted loop bodies
  1127. // If the function has bailout instructions, we keep the loop bodies alive
  1128. // in case we bail out to the interpreter, so that we can reuse the jitted
  1129. // loop bodies
  1130. func->GetJnFunction()->SetHasBailoutInstrInJittedCode(true);
  1131. return bailOutInstr;
  1132. }
  1133. template <typename InstrType>
  1134. BailOutInstrTemplate<InstrType> *
  1135. BailOutInstrTemplate<InstrType>::CloneBailOut() const
  1136. {
  1137. Assert(this->m_func->hasBailout);
  1138. Assert(!this->bailOutInfo->wasCloned);
  1139. BailOutInstrTemplate * bailOutInstr = BailOutInstrTemplate::New(this->m_opcode, this->bailOutKind, this->bailOutInfo, this->bailOutInfo->bailOutFunc);
  1140. bailOutInstr->hasAuxBailOut = this->hasAuxBailOut;
  1141. bailOutInstr->auxBailOutKind = this->auxBailOutKind;
  1142. bailOutInstr->bailOutInfo->wasCloned = true;
  1143. // the new copy is in the slow path and generate the real bailout
  1144. bailOutInstr->bailOutInfo->bailOutInstr = bailOutInstr;
  1145. return bailOutInstr;
  1146. }
  1147. template class BailOutInstrTemplate<IR::Instr>;
  1148. ///----------------------------------------------------------------------------
  1149. ///
  1150. /// EntryInstr::New
  1151. ///
  1152. /// Create an EntryInstr.
  1153. ///
  1154. ///----------------------------------------------------------------------------
  1155. EntryInstr *
  1156. EntryInstr::New(Js::OpCode opcode, Func *func)
  1157. {
  1158. EntryInstr * entryInstr;
  1159. entryInstr = JitAnew(func->m_alloc, IR::EntryInstr);
  1160. entryInstr->Init(opcode, InstrKindEntry, func);
  1161. return entryInstr;
  1162. }
  1163. ///----------------------------------------------------------------------------
  1164. ///
  1165. /// ExitInstr::New
  1166. ///
  1167. /// Create an ExitInstr.
  1168. ///
  1169. ///----------------------------------------------------------------------------
  1170. ExitInstr *
  1171. ExitInstr::New(Js::OpCode opcode, Func *func)
  1172. {
  1173. ExitInstr * exitInstr;
  1174. exitInstr = JitAnew(func->m_alloc, IR::ExitInstr);
  1175. exitInstr->Init(opcode, InstrKindExit, func);
  1176. return exitInstr;
  1177. }
  1178. ///----------------------------------------------------------------------------
  1179. ///
  1180. /// LabelInstr::New
  1181. ///
  1182. /// Create a label.
  1183. ///
  1184. ///----------------------------------------------------------------------------
  1185. LabelInstr *
  1186. LabelInstr::New(Js::OpCode opcode, Func *func, bool isOpHelper)
  1187. {
  1188. LabelInstr * labelInstr;
  1189. labelInstr = JitAnew(func->m_alloc, IR::LabelInstr, func->m_alloc);
  1190. labelInstr->Init(opcode, InstrKindLabel, func, isOpHelper);
  1191. return labelInstr;
  1192. }
  1193. void
  1194. LabelInstr::Init(Js::OpCode opcode, IRKind kind, Func *func, bool isOpHelper)
  1195. {
  1196. // Pass in the region when this is called from anywhere between the Lowerer and EHBailoutPatchUp code?
  1197. __super::Init(opcode, kind, func);
  1198. this->isOpHelper = isOpHelper;
  1199. this->m_pc.pc = nullptr;
  1200. this->m_id = ++(func->GetTopFunc()->m_labelCount);
  1201. AssertMsg(this->m_id != 0, "Label numbers wrapped around??!?");
  1202. }
  1203. ///----------------------------------------------------------------------------
  1204. ///
  1205. /// LabelInstr::AddLabelRef
  1206. ///
  1207. /// Add a branch to the list of label references.
  1208. ///
  1209. ///----------------------------------------------------------------------------
  1210. void
  1211. LabelInstr::AddLabelRef(BranchInstr *branchRef)
  1212. {
  1213. this->labelRefs.Prepend(branchRef);
  1214. }
  1215. ///----------------------------------------------------------------------------
  1216. ///
  1217. /// LabelInstr::RemoveLabelRef
  1218. ///
  1219. /// Remove a branch from the list of label references.
  1220. ///
  1221. ///----------------------------------------------------------------------------
  1222. void
  1223. LabelInstr::RemoveLabelRef(BranchInstr *branchRef)
  1224. {
  1225. FOREACH_SLISTCOUNTED_ENTRY_EDITING(BranchInstr*, branchEntry, &this->labelRefs, iter)
  1226. {
  1227. if (branchEntry == branchRef)
  1228. {
  1229. iter.RemoveCurrent();
  1230. return;
  1231. }
  1232. } NEXT_SLISTCOUNTED_ENTRY_EDITING;
  1233. AssertMsg(UNREACHED, "Branch not found on labelRef list");
  1234. }
  1235. ///----------------------------------------------------------------------------
  1236. ///
  1237. /// BranchInstr::New
  1238. ///
  1239. /// Create a Br (unconditional) BranchInstr.
  1240. ///
  1241. ///----------------------------------------------------------------------------
  1242. BranchInstr *
  1243. BranchInstr::New(Js::OpCode opcode, LabelInstr * branchTarget, Func *func)
  1244. {
  1245. BranchInstr * branchInstr;
  1246. branchInstr = JitAnew(func->m_alloc, IR::BranchInstr);
  1247. branchInstr->Init(opcode, InstrKindBranch, func);
  1248. branchInstr->SetTarget(branchTarget);
  1249. branchInstr->m_dst = nullptr;
  1250. branchInstr->m_src1 = nullptr;
  1251. branchInstr->m_src2 = nullptr;
  1252. branchInstr->m_byteCodeReg = Js::Constants::NoRegister;
  1253. #if DBG
  1254. branchInstr->m_isHelperToNonHelperBranch = false;
  1255. #endif
  1256. return branchInstr;
  1257. }
  1258. ///----------------------------------------------------------------------------
  1259. ///
  1260. /// BranchInstr::New
  1261. ///
  1262. /// Create a BrB BranchInstr (1-operand conditional branch).
  1263. ///
  1264. ///----------------------------------------------------------------------------
  1265. BranchInstr *
  1266. BranchInstr::New(Js::OpCode opcode, LabelInstr * branchTarget, Opnd *srcOpnd, Func *func)
  1267. {
  1268. BranchInstr * branchInstr;
  1269. branchInstr = BranchInstr::New(opcode, branchTarget, func);
  1270. branchInstr->SetSrc1(srcOpnd);
  1271. return branchInstr;
  1272. }
  1273. ///----------------------------------------------------------------------------
  1274. ///
  1275. /// BranchInstr::New
  1276. ///
  1277. /// Create a BrBReturn BranchInstr (1-operand conditional branch. If condition fails return the result of the condition).
  1278. ///
  1279. ///----------------------------------------------------------------------------
  1280. BranchInstr *
  1281. BranchInstr::New(Js::OpCode opcode, Opnd* destOpnd, LabelInstr * branchTarget, Opnd *srcOpnd, Func *func)
  1282. {
  1283. BranchInstr * branchInstr;
  1284. branchInstr = BranchInstr::New(opcode, branchTarget, func);
  1285. branchInstr->SetSrc1(srcOpnd);
  1286. branchInstr->SetDst(destOpnd);
  1287. return branchInstr;
  1288. }
  1289. ///----------------------------------------------------------------------------
  1290. ///
  1291. /// BranchInstr::New
  1292. ///
  1293. /// Create a BrReg2 BranchInstr (2-operand conditional branch).
  1294. ///
  1295. ///----------------------------------------------------------------------------
  1296. BranchInstr *
  1297. BranchInstr::New(Js::OpCode opcode, LabelInstr * branchTarget, Opnd *src1Opnd, Opnd *src2Opnd, Func *func)
  1298. {
  1299. BranchInstr * branchInstr;
  1300. branchInstr = BranchInstr::New(opcode, branchTarget, src1Opnd, func);
  1301. branchInstr->SetSrc2(src2Opnd);
  1302. return branchInstr;
  1303. }
  1304. ///----------------------------------------------------------------------------
  1305. ///
  1306. /// MultiBranchInstr::New
  1307. ///
  1308. /// Create a MultiBr BranchInstr (unconditional multi branch).
  1309. ///
  1310. ///----------------------------------------------------------------------------
  1311. MultiBranchInstr *
  1312. MultiBranchInstr::New(Js::OpCode opcode, IR::Opnd * srcOpnd, Func * func)
  1313. {
  1314. MultiBranchInstr * multiBranchInstr;
  1315. multiBranchInstr = MultiBranchInstr::New(opcode, func);
  1316. multiBranchInstr->SetSrc1(srcOpnd);
  1317. return multiBranchInstr;
  1318. }
  1319. MultiBranchInstr *
  1320. MultiBranchInstr::New(Js::OpCode opcode, Func * func)
  1321. {
  1322. JitArenaAllocator * m_funcAlloc = func->m_alloc;
  1323. MultiBranchInstr * multiBranchInstr;
  1324. multiBranchInstr = JitAnew(m_funcAlloc, IR::MultiBranchInstr);
  1325. multiBranchInstr->Init(opcode, InstrKindBranch, func);
  1326. return multiBranchInstr;
  1327. }
  1328. bool
  1329. BranchInstr::ReplaceTarget(IR::LabelInstr * oldLabelInstr, IR::LabelInstr * newLabelInstr)
  1330. {
  1331. if (this->IsMultiBranch())
  1332. {
  1333. return this->AsMultiBrInstr()->ReplaceTarget(oldLabelInstr, newLabelInstr);
  1334. }
  1335. if (this->GetTarget() == oldLabelInstr)
  1336. {
  1337. this->SetTarget(newLabelInstr);
  1338. return true;
  1339. }
  1340. return false;
  1341. }
  1342. bool
  1343. MultiBranchInstr::ReplaceTarget(IR::LabelInstr * oldLabelInstr, IR::LabelInstr * newLabelInstr)
  1344. {
  1345. Assert(this->IsMultiBranch());
  1346. bool remapped = false;
  1347. this->UpdateMultiBrLabels([=, &remapped](IR::LabelInstr * targetLabel) -> IR::LabelInstr *
  1348. {
  1349. if (targetLabel == oldLabelInstr)
  1350. {
  1351. this->ChangeLabelRef(targetLabel, newLabelInstr);
  1352. remapped = true;
  1353. return newLabelInstr;
  1354. }
  1355. return targetLabel;
  1356. });
  1357. return remapped;
  1358. }
  1359. void
  1360. MultiBranchInstr::ClearTarget()
  1361. {
  1362. Assert(IsMultiBranch());
  1363. MapMultiBrLabels([&](LabelInstr *const targetLabel)
  1364. {
  1365. ChangeLabelRef(targetLabel, nullptr);
  1366. });
  1367. m_branchTargets = nullptr;
  1368. }
  1369. BranchInstr *
  1370. BranchInstr::CloneBranchInstr() const
  1371. {
  1372. AssertMsg(!this->IsMultiBranch(),"Cloning Not supported for MultiBranchInstr");
  1373. Func * func = this->m_func;
  1374. // See if the target has already been cloned.
  1375. IR::LabelInstr * instrLabel = this->GetTarget()->CloneLabel(false);
  1376. if (instrLabel == nullptr)
  1377. {
  1378. // We didn't find a clone for this label.
  1379. // We'll go back and retarget the cloned branch if the target turns up in the cloned range.
  1380. instrLabel = this->GetTarget();
  1381. func->GetCloner()->fRetargetClonedBranch = TRUE;
  1382. }
  1383. return IR::BranchInstr::New(this->m_opcode, instrLabel, func);
  1384. }
  1385. void
  1386. BranchInstr::Invert()
  1387. {
  1388. /*
  1389. * If one of the operands to a relational operator is 'undefined', the result
  1390. * is always false. Don't invert such branches as they result in a jump to
  1391. * the wrong target.
  1392. */
  1393. switch (this->m_opcode)
  1394. {
  1395. case Js::OpCode::BrGt_A:
  1396. this->m_opcode = Js::OpCode::BrNotGt_A;
  1397. break;
  1398. case Js::OpCode::BrNotGt_A:
  1399. this->m_opcode = Js::OpCode::BrGt_A;
  1400. break;
  1401. case Js::OpCode::BrGe_A:
  1402. this->m_opcode = Js::OpCode::BrNotGe_A;
  1403. break;
  1404. case Js::OpCode::BrNotGe_A:
  1405. this->m_opcode = Js::OpCode::BrGe_A;
  1406. break;
  1407. case Js::OpCode::BrLt_A:
  1408. this->m_opcode = Js::OpCode::BrNotLt_A;
  1409. break;
  1410. case Js::OpCode::BrNotLt_A:
  1411. this->m_opcode = Js::OpCode::BrLt_A;
  1412. break;
  1413. case Js::OpCode::BrLe_A:
  1414. this->m_opcode = Js::OpCode::BrNotLe_A;
  1415. break;
  1416. case Js::OpCode::BrNotLe_A:
  1417. this->m_opcode = Js::OpCode::BrLe_A;
  1418. break;
  1419. case Js::OpCode::BrEq_A:
  1420. this->m_opcode = Js::OpCode::BrNotEq_A;
  1421. break;
  1422. case Js::OpCode::BrNotEq_A:
  1423. this->m_opcode = Js::OpCode::BrEq_A;
  1424. break;
  1425. case Js::OpCode::BrNeq_A:
  1426. this->m_opcode = Js::OpCode::BrNotNeq_A;
  1427. break;
  1428. case Js::OpCode::BrNotNeq_A:
  1429. this->m_opcode = Js::OpCode::BrNeq_A;
  1430. break;
  1431. case Js::OpCode::Br:
  1432. break;
  1433. case Js::OpCode::BrFalse_A:
  1434. this->m_opcode = Js::OpCode::BrTrue_A;
  1435. break;
  1436. case Js::OpCode::BrTrue_A:
  1437. this->m_opcode = Js::OpCode::BrFalse_A;
  1438. break;
  1439. case Js::OpCode::BrSrEq_A:
  1440. this->m_opcode = Js::OpCode::BrSrNotEq_A;
  1441. break;
  1442. case Js::OpCode::BrSrNotEq_A:
  1443. this->m_opcode = Js::OpCode::BrSrEq_A;
  1444. break;
  1445. case Js::OpCode::BrSrNeq_A:
  1446. this->m_opcode = Js::OpCode::BrSrNotNeq_A;
  1447. break;
  1448. case Js::OpCode::BrSrNotNeq_A:
  1449. this->m_opcode = Js::OpCode::BrSrNeq_A;
  1450. break;
  1451. case Js::OpCode::BrOnHasProperty:
  1452. this->m_opcode = Js::OpCode::BrOnNoProperty;
  1453. break;
  1454. case Js::OpCode::BrOnNoProperty:
  1455. this->m_opcode = Js::OpCode::BrOnHasProperty;
  1456. break;
  1457. case Js::OpCode::BrTrue_I4:
  1458. this->m_opcode = Js::OpCode::BrFalse_I4;
  1459. break;
  1460. case Js::OpCode::BrFalse_I4:
  1461. this->m_opcode = Js::OpCode::BrTrue_I4;
  1462. break;
  1463. case Js::OpCode::BrEq_I4:
  1464. this->m_opcode = Js::OpCode::BrNeq_I4;
  1465. break;
  1466. case Js::OpCode::BrNeq_I4:
  1467. this->m_opcode = Js::OpCode::BrEq_I4;
  1468. break;
  1469. case Js::OpCode::BrGe_I4:
  1470. this->m_opcode = Js::OpCode::BrLt_I4;
  1471. break;
  1472. case Js::OpCode::BrGt_I4:
  1473. this->m_opcode = Js::OpCode::BrLe_I4;
  1474. break;
  1475. case Js::OpCode::BrLe_I4:
  1476. this->m_opcode = Js::OpCode::BrGt_I4;
  1477. break;
  1478. case Js::OpCode::BrLt_I4:
  1479. this->m_opcode = Js::OpCode::BrGe_I4;
  1480. break;
  1481. case Js::OpCode::BrUnGe_A:
  1482. this->m_opcode = Js::OpCode::BrUnLt_A;
  1483. break;
  1484. case Js::OpCode::BrUnGt_A:
  1485. this->m_opcode = Js::OpCode::BrUnLe_A;
  1486. break;
  1487. case Js::OpCode::BrUnLe_A:
  1488. this->m_opcode = Js::OpCode::BrUnGt_A;
  1489. break;
  1490. case Js::OpCode::BrUnLt_A:
  1491. this->m_opcode = Js::OpCode::BrUnGe_A;
  1492. break;
  1493. case Js::OpCode::BrUnGe_I4:
  1494. this->m_opcode = Js::OpCode::BrUnLt_I4;
  1495. break;
  1496. case Js::OpCode::BrUnGt_I4:
  1497. this->m_opcode = Js::OpCode::BrUnLe_I4;
  1498. break;
  1499. case Js::OpCode::BrUnLe_I4:
  1500. this->m_opcode = Js::OpCode::BrUnGt_I4;
  1501. break;
  1502. case Js::OpCode::BrUnLt_I4:
  1503. this->m_opcode = Js::OpCode::BrUnGe_I4;
  1504. break;
  1505. case Js::OpCode::BrOnEmpty:
  1506. this->m_opcode = Js::OpCode::BrOnNotEmpty;
  1507. break;
  1508. case Js::OpCode::BrOnNotEmpty:
  1509. this->m_opcode = Js::OpCode::BrOnEmpty;
  1510. break;
  1511. case Js::OpCode::BrHasSideEffects:
  1512. this->m_opcode = Js::OpCode::BrNotHasSideEffects;
  1513. break;
  1514. case Js::OpCode::BrFncEqApply:
  1515. this->m_opcode = Js::OpCode::BrFncNeqApply;
  1516. break;
  1517. case Js::OpCode::BrFncNeqApply:
  1518. this->m_opcode = Js::OpCode::BrFncEqApply;
  1519. break;
  1520. case Js::OpCode::BrNotHasSideEffects:
  1521. this->m_opcode = Js::OpCode::BrHasSideEffects;
  1522. break;
  1523. case Js::OpCode::BrNotAddr_A:
  1524. this->m_opcode = Js::OpCode::BrAddr_A;
  1525. break;
  1526. case Js::OpCode::BrAddr_A:
  1527. this->m_opcode = Js::OpCode::BrNotAddr_A;
  1528. break;
  1529. case Js::OpCode::BrFncCachedScopeEq:
  1530. this->m_opcode = Js::OpCode::BrFncCachedScopeNeq;
  1531. break;
  1532. case Js::OpCode::BrFncCachedScopeNeq:
  1533. this->m_opcode = Js::OpCode::BrFncCachedScopeEq;
  1534. break;
  1535. case Js::OpCode::BrOnException:
  1536. this->m_opcode = Js::OpCode::BrOnNoException;
  1537. break;
  1538. default:
  1539. AssertMsg(UNREACHED, "Unhandled branch");
  1540. }
  1541. }
  1542. bool
  1543. BranchInstr::IsLoopTail(Func * func)
  1544. {
  1545. Assert(func->isPostLower);
  1546. IR::LabelInstr * target = this->GetTarget();
  1547. if (!target->m_isLoopTop)
  1548. {
  1549. return false;
  1550. }
  1551. IR::BranchInstr * lastBranchInstr = nullptr;
  1552. uint32 lastBranchNum = 0;
  1553. FOREACH_SLISTCOUNTED_ENTRY(IR::BranchInstr *, ref, &target->labelRefs)
  1554. {
  1555. if (ref->GetNumber() > lastBranchNum)
  1556. {
  1557. lastBranchInstr = ref;
  1558. lastBranchNum = lastBranchInstr->GetNumber();
  1559. }
  1560. }
  1561. NEXT_SLISTCOUNTED_ENTRY;
  1562. if (this == lastBranchInstr)
  1563. {
  1564. return true;
  1565. }
  1566. return false;
  1567. }
  1568. ///----------------------------------------------------------------------------
  1569. ///
  1570. /// PragmaInstr::New
  1571. ///
  1572. /// Create a PragmaInstr.
  1573. ///
  1574. ///----------------------------------------------------------------------------
  1575. PragmaInstr *
  1576. PragmaInstr::New(Js::OpCode opcode, uint32 index, Func *func)
  1577. {
  1578. PragmaInstr * pragmaInstr;
  1579. pragmaInstr = JitAnew(func->m_alloc, IR::PragmaInstr);
  1580. pragmaInstr->Init(opcode, InstrKindPragma, func);
  1581. pragmaInstr->m_statementIndex = index;
  1582. return pragmaInstr;
  1583. }
  1584. ///----------------------------------------------------------------------------
  1585. ///
  1586. /// PragmaInstr::Instr
  1587. ///
  1588. /// Record the information encoded in the pragma
  1589. ///
  1590. ///----------------------------------------------------------------------------
  1591. #if DBG_DUMP | defined(VTUNE_PROFILING)
  1592. void
  1593. PragmaInstr::Record(uint32 nativeBufferOffset)
  1594. {
  1595. // Currently the only pragma instructions are for Source Info
  1596. Assert(this->m_func->GetTopFunc()->DoRecordNativeMap());
  1597. this->m_func->GetTopFunc()->m_workItem->RecordNativeMap(nativeBufferOffset, m_statementIndex);
  1598. }
  1599. #endif
  1600. void
  1601. PragmaInstr::RecordThrowMap(Js::SmallSpanSequenceIter& iter, uint32 nativeBufferOffset)
  1602. {
  1603. m_func->GetTopFunc()->m_workItem->RecordNativeThrowMap(iter, nativeBufferOffset, m_statementIndex);
  1604. }
  1605. ///----------------------------------------------------------------------------
  1606. ///
  1607. /// Instr::New
  1608. ///
  1609. /// Create an Instr.
  1610. ///
  1611. ///----------------------------------------------------------------------------
  1612. Instr *
  1613. Instr::New(Js::OpCode opcode, Func *func)
  1614. {
  1615. Instr * instr;
  1616. instr = JitAnew(func->m_alloc, IR::Instr);
  1617. instr->Init(opcode, InstrKindInstr, func);
  1618. return instr;
  1619. }
  1620. ///----------------------------------------------------------------------------
  1621. ///
  1622. /// Instr::New
  1623. ///
  1624. /// Create an Instr with dst.
  1625. ///
  1626. ///----------------------------------------------------------------------------
  1627. Instr *
  1628. Instr::New(Js::OpCode opcode, Opnd *dstOpnd, Func *func)
  1629. {
  1630. Instr * instr;
  1631. instr = Instr::New(opcode, func);
  1632. instr->SetDst(dstOpnd);
  1633. return instr;
  1634. }
  1635. ///----------------------------------------------------------------------------
  1636. ///
  1637. /// Instr::New
  1638. ///
  1639. /// Create an Instr with dst and a src.
  1640. ///
  1641. ///----------------------------------------------------------------------------
  1642. Instr *
  1643. Instr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Func *func)
  1644. {
  1645. Instr * instr;
  1646. instr = Instr::New(opcode, dstOpnd, func);
  1647. instr->SetSrc1(src1Opnd);
  1648. return instr;
  1649. }
  1650. ///----------------------------------------------------------------------------
  1651. ///
  1652. /// Instr::New
  1653. ///
  1654. /// Create an Instr with dst and 2 srcs.
  1655. ///
  1656. ///----------------------------------------------------------------------------
  1657. Instr *
  1658. Instr::New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Opnd *src2Opnd, Func *func)
  1659. {
  1660. Instr * instr;
  1661. instr = Instr::New(opcode, dstOpnd, src1Opnd, func);
  1662. instr->SetSrc2(src2Opnd);
  1663. return instr;
  1664. }
  1665. ///----------------------------------------------------------------------------
  1666. ///
  1667. /// Instr::SetDst
  1668. ///
  1669. /// Set the dst for 'this' instruction. Automatically maintain isSingleDef
  1670. /// and instrDef of stackSyms.
  1671. ///
  1672. ///----------------------------------------------------------------------------
  1673. Opnd *
  1674. Instr::SetDst(Opnd * newDst)
  1675. {
  1676. AssertMsg(newDst != nullptr, "Calling SetDst with a NULL dst");
  1677. AssertMsg(this->m_dst == nullptr, "Calling SetDst without unlinking/freeing the current dst");
  1678. Assert(!(newDst->IsRegOpnd() && newDst->AsRegOpnd()->IsSymValueFrozen()));
  1679. newDst = newDst->Use(m_func);
  1680. this->m_dst = newDst;
  1681. // If newDst isSingleDef, set instrDef
  1682. StackSym *stackSym;
  1683. if (newDst->IsRegOpnd() && newDst->AsRegOpnd()->m_sym)
  1684. {
  1685. stackSym = newDst->AsRegOpnd()->m_sym->AsStackSym();
  1686. }
  1687. else if (newDst->IsSymOpnd() && newDst->AsSymOpnd()->m_sym->IsStackSym())
  1688. {
  1689. stackSym = newDst->AsSymOpnd()->m_sym->AsStackSym();
  1690. }
  1691. else
  1692. {
  1693. stackSym = nullptr;
  1694. }
  1695. if (stackSym && stackSym->m_isSingleDef)
  1696. {
  1697. if (stackSym->m_instrDef)
  1698. {
  1699. AssertMsg(!stackSym->IsArgSlotSym(), "Arg Slot sym needs to be single def to maintain the StartCall arg links");
  1700. // Multiple defs, clear isSingleDef flag
  1701. stackSym->m_isSingleDef = false;
  1702. stackSym->m_instrDef = nullptr;
  1703. stackSym->m_isConst = false;
  1704. stackSym->m_isIntConst = false;
  1705. stackSym->m_isTaggableIntConst = false;
  1706. stackSym->m_isNotInt = false;
  1707. stackSym->m_isStrConst = false;
  1708. stackSym->m_isStrEmpty = false;
  1709. stackSym->m_isFltConst = false;
  1710. }
  1711. else
  1712. {
  1713. stackSym->m_instrDef = this;
  1714. }
  1715. }
  1716. return newDst;
  1717. }
  1718. Opnd *
  1719. Instr::SetFakeDst(Opnd * newDst)
  1720. {
  1721. AssertMsg(newDst != nullptr, "Calling SetDst with a NULL dst");
  1722. AssertMsg(this->m_dst == nullptr, "Calling SetDst without unlinking/freeing the current dst");
  1723. Assert(!(newDst->IsRegOpnd() && newDst->AsRegOpnd()->IsSymValueFrozen()));
  1724. newDst = newDst->Use(m_func);
  1725. this->m_dst = newDst;
  1726. #if DBG
  1727. newDst->isFakeDst = true;
  1728. #endif
  1729. return newDst;
  1730. }
  1731. ///----------------------------------------------------------------------------
  1732. ///
  1733. /// Instr::UnlinkDst
  1734. ///
  1735. /// Unlinks the dst for 'this' instruction. Automatically maintains
  1736. /// instrDef of stackSyms.
  1737. ///
  1738. ///----------------------------------------------------------------------------
  1739. Opnd *
  1740. Instr::UnlinkDst()
  1741. {
  1742. Opnd * oldDst = this->m_dst;
  1743. StackSym *stackSym = nullptr;
  1744. // If oldDst isSingleDef, clear instrDef
  1745. if (oldDst->IsRegOpnd())
  1746. {
  1747. stackSym = oldDst->AsRegOpnd()->m_sym;
  1748. }
  1749. else if (oldDst->IsSymOpnd())
  1750. {
  1751. Sym *sym = oldDst->AsSymOpnd()->m_sym;
  1752. if (sym->IsStackSym())
  1753. {
  1754. stackSym = sym->AsStackSym();
  1755. }
  1756. }
  1757. #if DBG
  1758. if (oldDst->isFakeDst)
  1759. {
  1760. oldDst->isFakeDst = false;
  1761. }
  1762. #endif
  1763. if (stackSym && stackSym->m_isSingleDef)
  1764. {
  1765. AssertMsg(stackSym->m_instrDef == this, "m_instrDef incorrectly set");
  1766. stackSym->m_instrDef = nullptr;
  1767. }
  1768. oldDst->UnUse();
  1769. this->m_dst = nullptr;
  1770. return oldDst;
  1771. }
  1772. ///----------------------------------------------------------------------------
  1773. ///
  1774. /// Instr::FreeDst
  1775. ///
  1776. /// Unlinks and free the dst for 'this' instruction.
  1777. ///
  1778. ///----------------------------------------------------------------------------
  1779. void
  1780. Instr::FreeDst()
  1781. {
  1782. Opnd * unlinkedDst;
  1783. unlinkedDst = this->UnlinkDst();
  1784. unlinkedDst->Free(this->m_func);
  1785. }
  1786. ///----------------------------------------------------------------------------
  1787. ///
  1788. /// Instr::ReplaceDst
  1789. ///
  1790. /// Unlink this dst from this instr, free it, and replace it with newDst.
  1791. /// The new dst is returned.
  1792. ///
  1793. ///----------------------------------------------------------------------------
  1794. Opnd *
  1795. Instr::ReplaceDst(Opnd * newDst)
  1796. {
  1797. this->FreeDst();
  1798. return this->SetDst(newDst);
  1799. }
  1800. ///----------------------------------------------------------------------------
  1801. ///
  1802. /// Instr::SinkDst
  1803. ///
  1804. /// Replace current dst with new symbol, and assign new symbol using the
  1805. /// given opcode to the previous dst.
  1806. ///
  1807. ///----------------------------------------------------------------------------
  1808. Instr *
  1809. Instr::SinkDst(Js::OpCode assignOpcode, RegNum regNum, IR::Instr *insertAfterInstr)
  1810. {
  1811. return SinkDst(assignOpcode, StackSym::New(TyVar, m_func), regNum, insertAfterInstr);
  1812. }
  1813. Instr *
  1814. Instr::SinkDst(Js::OpCode assignOpcode, StackSym * stackSym, RegNum regNum, IR::Instr *insertAfterInstr)
  1815. {
  1816. if(!insertAfterInstr)
  1817. {
  1818. insertAfterInstr = this;
  1819. }
  1820. Opnd *oldDst, *newDst;
  1821. Instr * newInstr;
  1822. IRType type;
  1823. oldDst = this->UnlinkDst();
  1824. type = oldDst->GetType();
  1825. newDst = this->SetDst(RegOpnd::New(stackSym, regNum, type, m_func));
  1826. newInstr = Instr::New(assignOpcode, oldDst, newDst, m_func);
  1827. insertAfterInstr->InsertAfter(newInstr);
  1828. return newInstr;
  1829. }
  1830. IR::Instr *
  1831. Instr::SinkInstrBefore(IR::Instr * instrTarget)
  1832. {
  1833. // Move this instruction down to the target location, preserving
  1834. // the use(s), if necessary, from redefinition between the original
  1835. // location and the new one.
  1836. if (this->m_next == instrTarget)
  1837. {
  1838. return this->m_prev;
  1839. }
  1840. StackSym *sym;
  1841. if (this->m_src1)
  1842. {
  1843. sym = this->m_src1->GetStackSym();
  1844. if (sym && !sym->m_isSingleDef)
  1845. {
  1846. this->HoistSrc1(Js::OpCode::Ld_A);
  1847. }
  1848. if (this->m_src2)
  1849. {
  1850. sym = this->m_src2->GetStackSym();
  1851. if (sym && !sym->m_isSingleDef)
  1852. {
  1853. this->HoistSrc2(Js::OpCode::Ld_A);
  1854. }
  1855. }
  1856. }
  1857. // Move the instruction down to the target. Return the instruction
  1858. // that preceded the sunk instruction at its original location.
  1859. // (This lets the caller find a Ld_A that this call inserted.)
  1860. IR::Instr * instrPrev = this->m_prev;
  1861. this->Unlink();
  1862. instrTarget->InsertBefore(this);
  1863. return instrPrev;
  1864. }
  1865. ///----------------------------------------------------------------------------
  1866. ///
  1867. /// Instr::UnlinkSrc1
  1868. ///
  1869. /// Unlinks the src1 for 'this' instruction.
  1870. ///
  1871. ///----------------------------------------------------------------------------
  1872. Opnd *
  1873. Instr::UnlinkSrc1()
  1874. {
  1875. Opnd * oldSrc = this->m_src1;
  1876. oldSrc->UnUse();
  1877. this->m_src1 = nullptr;
  1878. return oldSrc;
  1879. }
  1880. ///----------------------------------------------------------------------------
  1881. ///
  1882. /// Instr::FreeSrc1
  1883. ///
  1884. /// Unlinks and free the src1 for 'this' instruction.
  1885. ///
  1886. ///----------------------------------------------------------------------------
  1887. void
  1888. Instr::FreeSrc1()
  1889. {
  1890. Opnd * unlinkedSrc;
  1891. unlinkedSrc = this->UnlinkSrc1();
  1892. unlinkedSrc->Free(this->m_func);
  1893. }
  1894. ///----------------------------------------------------------------------------
  1895. ///
  1896. /// Instr::ReplaceSrc1
  1897. ///
  1898. /// Unlink src1 from this instr, free it, and replace it with newSrc.
  1899. /// The new src is returned.
  1900. ///
  1901. ///----------------------------------------------------------------------------
  1902. Opnd *
  1903. Instr::ReplaceSrc1(Opnd * newSrc)
  1904. {
  1905. this->FreeSrc1();
  1906. return this->SetSrc1(newSrc);
  1907. }
  1908. ///----------------------------------------------------------------------------
  1909. ///
  1910. /// Instr::HoistSrc1
  1911. ///
  1912. /// Replace current src with new symbol, and assign new symbol using the
  1913. /// given opcode from the previous src.
  1914. ///
  1915. ///----------------------------------------------------------------------------
  1916. Instr *
  1917. Instr::HoistSrc1(Js::OpCode assignOpcode, RegNum regNum, StackSym *newSym)
  1918. {
  1919. Opnd *oldSrc, *newSrc;
  1920. Instr * newInstr;
  1921. IRType type;
  1922. oldSrc = this->UnlinkSrc1();
  1923. type = oldSrc->GetType();
  1924. const bool creatingNewSym = !newSym;
  1925. if(creatingNewSym)
  1926. {
  1927. newSym = StackSym::New(type, m_func);
  1928. }
  1929. newSrc = this->SetSrc1(RegOpnd::New(newSym, regNum, type, m_func));
  1930. newSrc->SetValueType(oldSrc->GetValueType());
  1931. newInstr = Instr::New(assignOpcode, newSrc, oldSrc, m_func);
  1932. this->InsertBefore(newInstr);
  1933. if(creatingNewSym)
  1934. {
  1935. if (oldSrc->IsRegOpnd())
  1936. {
  1937. newSym->CopySymAttrs(oldSrc->AsRegOpnd()->m_sym);
  1938. }
  1939. else if (oldSrc->IsImmediateOpnd())
  1940. {
  1941. newSym->SetIsConst();
  1942. }
  1943. }
  1944. return newInstr;
  1945. }
  1946. bool
  1947. Instr::IsSrc1FunctionObject()
  1948. {
  1949. if (!this->GetSrc1())
  1950. {
  1951. return false;
  1952. }
  1953. if (this->GetSrc1()->IsAddrOpnd())
  1954. {
  1955. return this->GetSrc1()->AsAddrOpnd()->m_isFunction;
  1956. }
  1957. if (this->GetSrc1()->IsRegOpnd())
  1958. {
  1959. return (this->GetSrc1()->AsRegOpnd()->m_sym->AsStackSym()->IsSingleDef() &&
  1960. this->GetSrc1()->AsRegOpnd()->m_sym->AsStackSym()->GetInstrDef()->GetSrc1()->IsAddrOpnd() &&
  1961. this->GetSrc1()->AsRegOpnd()->m_sym->AsStackSym()->GetInstrDef()->GetSrc1()->AsAddrOpnd()->m_isFunction);
  1962. }
  1963. return false;
  1964. }
  1965. ///----------------------------------------------------------------------------
  1966. ///
  1967. /// Instr::UnlinkSrc2
  1968. ///
  1969. /// Unlinks the src2 for 'this' instruction.
  1970. ///
  1971. ///----------------------------------------------------------------------------
  1972. Opnd *
  1973. Instr::UnlinkSrc2()
  1974. {
  1975. Opnd * oldSrc = this->m_src2;
  1976. oldSrc->UnUse();
  1977. this->m_src2 = nullptr;
  1978. return oldSrc;
  1979. }
  1980. ///----------------------------------------------------------------------------
  1981. ///
  1982. /// Instr::FreeSrc2
  1983. ///
  1984. /// Unlinks and free the src2 for 'this' instruction.
  1985. ///
  1986. ///----------------------------------------------------------------------------
  1987. void
  1988. Instr::FreeSrc2()
  1989. {
  1990. Opnd * unlinkedSrc;
  1991. unlinkedSrc = this->UnlinkSrc2();
  1992. unlinkedSrc->Free(this->m_func);
  1993. }
  1994. ///----------------------------------------------------------------------------
  1995. ///
  1996. /// Instr::ReplaceSrc2
  1997. ///
  1998. /// Unlink src2 from this instr, free it, and replace it with newSrc.
  1999. /// The new src is returned.
  2000. ///
  2001. ///----------------------------------------------------------------------------
  2002. Opnd *
  2003. Instr::ReplaceSrc2(Opnd * newSrc)
  2004. {
  2005. this->FreeSrc2();
  2006. return this->SetSrc2(newSrc);
  2007. }
  2008. ///----------------------------------------------------------------------------
  2009. ///
  2010. /// Instr::HoistSrc2
  2011. ///
  2012. /// Replace current src with new symbol, and assign new symbol using the
  2013. /// given opcode from the previous src.
  2014. ///
  2015. ///----------------------------------------------------------------------------
  2016. Instr *
  2017. Instr::HoistSrc2(Js::OpCode assignOpcode, RegNum regNum, StackSym *newSym)
  2018. {
  2019. Opnd *oldSrc, *newSrc;
  2020. Instr * newInstr;
  2021. IRType type;
  2022. oldSrc = this->UnlinkSrc2();
  2023. type = oldSrc->GetType();
  2024. const bool creatingNewSym = !newSym;
  2025. if(creatingNewSym)
  2026. {
  2027. newSym = StackSym::New(type, m_func);
  2028. }
  2029. newSrc = this->SetSrc2(RegOpnd::New(newSym, regNum, type, m_func));
  2030. newSrc->SetValueType(oldSrc->GetValueType());
  2031. newInstr = Instr::New(assignOpcode, newSrc, oldSrc, m_func);
  2032. this->InsertBefore(newInstr);
  2033. if(creatingNewSym)
  2034. {
  2035. if (oldSrc->IsRegOpnd())
  2036. {
  2037. newSym->CopySymAttrs(oldSrc->AsRegOpnd()->m_sym);
  2038. }
  2039. else if (oldSrc->IsIntConstOpnd())
  2040. {
  2041. newSym->SetIsIntConst(oldSrc->AsIntConstOpnd()->GetValue());
  2042. }
  2043. }
  2044. return newInstr;
  2045. }
  2046. ///----------------------------------------------------------------------------
  2047. ///
  2048. /// Instr::HoistIndirOffset
  2049. ///
  2050. /// Replace the offset of the given indir with a new symbol, which becomes the indir index.
  2051. /// Assign the new symbol by creating an assignment from the constant offset.
  2052. ///
  2053. ///----------------------------------------------------------------------------
  2054. Instr *
  2055. Instr::HoistIndirOffset(IR::IndirOpnd *indirOpnd, RegNum regNum)
  2056. {
  2057. int32 offset = indirOpnd->GetOffset();
  2058. if (indirOpnd->GetIndexOpnd())
  2059. {
  2060. return HoistIndirOffsetAsAdd(indirOpnd, indirOpnd->GetBaseOpnd(), offset, regNum);
  2061. }
  2062. IntConstOpnd *offsetOpnd = IntConstOpnd::New(offset, TyInt32, this->m_func);
  2063. RegOpnd *indexOpnd = RegOpnd::New(StackSym::New(TyMachReg, this->m_func), regNum, TyMachReg, this->m_func);
  2064. #if defined(DBG) && defined(_M_ARM)
  2065. if (regNum == SCRATCH_REG)
  2066. {
  2067. AssertMsg(indirOpnd->GetBaseOpnd()->GetReg()!= SCRATCH_REG, "Why both are SCRATCH_REG");
  2068. if (this->GetSrc1() && this->GetSrc1()->IsRegOpnd())
  2069. {
  2070. Assert(this->GetSrc1()->AsRegOpnd()->GetReg() != SCRATCH_REG);
  2071. }
  2072. if (this->GetSrc2() && this->GetSrc2()->IsRegOpnd())
  2073. {
  2074. Assert(this->GetSrc2()->AsRegOpnd()->GetReg() != SCRATCH_REG);
  2075. }
  2076. if (this->GetDst() && this->GetDst()->IsRegOpnd())
  2077. {
  2078. Assert(this->GetDst()->AsRegOpnd()->GetReg() != SCRATCH_REG);
  2079. }
  2080. }
  2081. #endif
  2082. // Clear the offset and add a new reg as the index.
  2083. indirOpnd->SetOffset(0);
  2084. indirOpnd->SetIndexOpnd(indexOpnd);
  2085. Instr *instrAssign = LowererMD::CreateAssign(indexOpnd, offsetOpnd, this);
  2086. indexOpnd->m_sym->SetIsIntConst(offset);
  2087. return instrAssign;
  2088. }
  2089. IndirOpnd *
  2090. Instr::HoistMemRefAddress(MemRefOpnd *const memRefOpnd, const Js::OpCode loadOpCode)
  2091. {
  2092. Assert(memRefOpnd);
  2093. #if defined(_M_IX86) || defined(_M_X64)
  2094. Assert(!LowererMDArch::IsLegalMemLoc(memRefOpnd));
  2095. #endif
  2096. void * address = memRefOpnd->GetMemLoc();
  2097. IR::AddrOpndKind kind = memRefOpnd->GetAddrKind();
  2098. Func *const func = m_func;
  2099. IR::IndirOpnd * indirOpnd = func->GetTopFunc()->GetConstantAddressIndirOpnd(address, kind, memRefOpnd->GetType(), loadOpCode);
  2100. if (indirOpnd == nullptr)
  2101. {
  2102. IR::RegOpnd * addressRegOpnd = IR::RegOpnd::New(TyMachPtr, func);
  2103. IR::Instr *const newInstr =
  2104. IR::Instr::New(
  2105. loadOpCode,
  2106. addressRegOpnd,
  2107. IR::AddrOpnd::New(address, kind, func, true),
  2108. func);
  2109. InsertBefore(newInstr);
  2110. indirOpnd = IR::IndirOpnd::New(addressRegOpnd, 0, memRefOpnd->GetType(), func, true);
  2111. #if DBG_DUMP
  2112. indirOpnd->SetAddrKind(kind, address);
  2113. #endif
  2114. }
  2115. return DeepReplace(memRefOpnd, indirOpnd)->AsIndirOpnd();
  2116. }
  2117. Opnd *
  2118. Instr::Replace(Opnd *oldOpnd, Opnd *newOpnd)
  2119. {
  2120. if (oldOpnd == this->GetDst())
  2121. {
  2122. return this->ReplaceDst(newOpnd);
  2123. }
  2124. else
  2125. {
  2126. return this->ReplaceSrc(oldOpnd, newOpnd);
  2127. }
  2128. }
  2129. Opnd *Instr::DeepReplace(Opnd *const oldOpnd, Opnd *const newOpnd)
  2130. {
  2131. Assert(oldOpnd);
  2132. Assert(newOpnd);
  2133. IR::Opnd *opnd = GetDst();
  2134. if(opnd && oldOpnd != opnd && oldOpnd->IsEqual(opnd))
  2135. {
  2136. ReplaceDst(newOpnd);
  2137. }
  2138. opnd = GetSrc1();
  2139. if(opnd && oldOpnd != opnd && oldOpnd->IsEqual(opnd))
  2140. {
  2141. ReplaceSrc1(newOpnd);
  2142. }
  2143. opnd = GetSrc2();
  2144. if(opnd && oldOpnd != opnd && oldOpnd->IsEqual(opnd))
  2145. {
  2146. ReplaceSrc2(newOpnd);
  2147. }
  2148. // Do this last because Replace will delete oldOpnd
  2149. return Replace(oldOpnd, newOpnd);
  2150. }
  2151. Instr *
  2152. Instr::HoistIndirOffsetAsAdd(IR::IndirOpnd *orgOpnd, IR::Opnd *baseOpnd, int offset, RegNum regNum)
  2153. {
  2154. IR::RegOpnd *newBaseOpnd = IR::RegOpnd::New(StackSym::New(TyMachPtr, this->m_func), regNum, TyMachPtr, this->m_func);
  2155. IR::IntConstOpnd *src2 = IR::IntConstOpnd::New(offset, TyInt32, this->m_func);
  2156. IR::Instr * instrAdd = IR::Instr::New(Js::OpCode::ADD, newBaseOpnd, baseOpnd, src2, this->m_func);
  2157. this->InsertBefore(instrAdd);
  2158. orgOpnd->ReplaceBaseOpnd(newBaseOpnd);
  2159. orgOpnd->SetOffset(0);
  2160. return instrAdd;
  2161. }
  2162. Instr *
  2163. Instr::HoistIndirIndexOpndAsAdd(IR::IndirOpnd *orgOpnd, IR::Opnd *baseOpnd, IR::Opnd *indexOpnd, RegNum regNum)
  2164. {
  2165. IR::RegOpnd *newBaseOpnd = IR::RegOpnd::New(StackSym::New(TyMachPtr, this->m_func), regNum, TyMachPtr, this->m_func);
  2166. IR::Instr * instrAdd = IR::Instr::New(Js::OpCode::ADD, newBaseOpnd, baseOpnd, indexOpnd, this->m_func);
  2167. this->InsertBefore(instrAdd);
  2168. orgOpnd->ReplaceBaseOpnd(newBaseOpnd);
  2169. orgOpnd->SetIndexOpnd(nullptr);
  2170. return instrAdd;
  2171. }
  2172. Instr *
  2173. Instr::HoistSymOffsetAsAdd(IR::SymOpnd *orgOpnd, IR::Opnd *baseOpnd, int offset, RegNum regNum)
  2174. {
  2175. IR::IndirOpnd *newIndirOpnd = IR::IndirOpnd::New(baseOpnd->AsRegOpnd(), 0, TyMachPtr, this->m_func);
  2176. this->Replace(orgOpnd, newIndirOpnd); // Replace SymOpnd with IndirOpnd
  2177. return this->HoistIndirOffsetAsAdd(newIndirOpnd, baseOpnd, offset, regNum);
  2178. }
  2179. ///----------------------------------------------------------------------------
  2180. ///
  2181. /// Instr::HoistSymOffset
  2182. ///
  2183. /// Replace the given sym with an indir using the given base and offset.
  2184. /// (This is used, for instance, to hoist a sym offset that is too large to encode.)
  2185. ///
  2186. ///----------------------------------------------------------------------------
  2187. Instr *
  2188. Instr::HoistSymOffset(SymOpnd *symOpnd, RegNum baseReg, uint32 offset, RegNum regNum)
  2189. {
  2190. IR::RegOpnd *baseOpnd = IR::RegOpnd::New(nullptr, baseReg, TyMachPtr, this->m_func);
  2191. IR::IndirOpnd *indirOpnd = IR::IndirOpnd::New(baseOpnd, offset, symOpnd->GetType(), this->m_func);
  2192. if (symOpnd == this->GetDst())
  2193. {
  2194. this->ReplaceDst(indirOpnd);
  2195. }
  2196. else
  2197. {
  2198. this->ReplaceSrc(symOpnd, indirOpnd);
  2199. }
  2200. return this->HoistIndirOffset(indirOpnd, regNum);
  2201. }
  2202. Opnd *
  2203. Instr::UnlinkSrc(Opnd *src)
  2204. {
  2205. if (src == this->GetSrc1())
  2206. {
  2207. return this->UnlinkSrc1();
  2208. }
  2209. else
  2210. {
  2211. AssertMsg(src == this->GetSrc2(), "Src not found");
  2212. return this->UnlinkSrc2();
  2213. }
  2214. }
  2215. ///----------------------------------------------------------------------------
  2216. ///
  2217. /// Instr::ReplaceSrc
  2218. ///
  2219. /// Unlink oldSrc from this instr, free it, and replace it with newSrc.
  2220. /// The new src is returned.
  2221. ///
  2222. ///----------------------------------------------------------------------------
  2223. Opnd *
  2224. Instr::ReplaceSrc(Opnd *oldSrc, Opnd * newSrc)
  2225. {
  2226. if (oldSrc == this->GetSrc1())
  2227. {
  2228. return this->ReplaceSrc1(newSrc);
  2229. }
  2230. else
  2231. {
  2232. AssertMsg(oldSrc == this->GetSrc2(), "OldSrc not found");
  2233. return this->ReplaceSrc2(newSrc);
  2234. }
  2235. }
  2236. ///----------------------------------------------------------------------------
  2237. ///
  2238. /// Instr::IsRealInstr
  2239. ///
  2240. /// Does this instr generate code?
  2241. ///
  2242. ///----------------------------------------------------------------------------
  2243. bool
  2244. Instr::IsRealInstr() const
  2245. {
  2246. switch (m_opcode)
  2247. {
  2248. case Js::OpCode::Label:
  2249. case Js::OpCode::StatementBoundary:
  2250. case Js::OpCode::NoImplicitCallUses:
  2251. case Js::OpCode::NoIntOverflowBoundary:
  2252. return false;
  2253. default:
  2254. return true;
  2255. }
  2256. }
  2257. ///----------------------------------------------------------------------------
  2258. ///
  2259. /// Instr::GetNextRealInstr
  2260. ///
  2261. ///----------------------------------------------------------------------------
  2262. IR::Instr *
  2263. Instr::GetNextRealInstr() const
  2264. {
  2265. IR::Instr *instr = this->m_next;
  2266. while (instr != nullptr && !instr->IsRealInstr())
  2267. {
  2268. AssertMsg(instr->m_next || instr->IsPragmaInstr(), "GetNextRealInstr() failed...");
  2269. instr = instr->m_next;
  2270. }
  2271. return instr;
  2272. }
  2273. ///----------------------------------------------------------------------------
  2274. ///
  2275. /// Instr::GetNextRealInstrOrLabel
  2276. ///
  2277. ///----------------------------------------------------------------------------
  2278. IR::Instr *
  2279. Instr::GetNextRealInstrOrLabel() const
  2280. {
  2281. IR::Instr *instr = this->m_next;
  2282. while (instr != nullptr && !instr->IsLabelInstr() && !instr->IsRealInstr())
  2283. {
  2284. instr = instr->m_next;
  2285. AssertMsg(instr, "GetNextRealInstrOrLabel() failed...");
  2286. }
  2287. return instr;
  2288. }
  2289. IR::Instr *
  2290. Instr::GetNextBranchOrLabel() const
  2291. {
  2292. IR::Instr *instr = this->m_next;
  2293. while (instr != nullptr && !instr->IsLabelInstr() && !instr->IsBranchInstr())
  2294. {
  2295. instr = instr->m_next;
  2296. }
  2297. return instr;
  2298. }
  2299. ///----------------------------------------------------------------------------
  2300. ///
  2301. /// Instr::GetPrevRealInstr
  2302. ///
  2303. ///----------------------------------------------------------------------------
  2304. IR::Instr *
  2305. Instr::GetPrevRealInstr() const
  2306. {
  2307. IR::Instr *instr = this->m_prev;
  2308. while (!instr->IsRealInstr())
  2309. {
  2310. instr = instr->m_prev;
  2311. AssertMsg(instr, "GetPrevRealInstr() failed...");
  2312. }
  2313. return instr;
  2314. }
  2315. ///----------------------------------------------------------------------------
  2316. ///
  2317. /// Instr::GetPrevRealInstrOrLabel
  2318. ///
  2319. ///----------------------------------------------------------------------------
  2320. IR::Instr *
  2321. Instr::GetPrevRealInstrOrLabel() const
  2322. {
  2323. IR::Instr *instr = this->m_prev;
  2324. while (!instr->IsLabelInstr() && !instr->IsRealInstr())
  2325. {
  2326. instr = instr->m_prev;
  2327. AssertMsg(instr, "GetPrevRealInstrOrLabel() failed...");
  2328. }
  2329. return instr;
  2330. }
  2331. ///----------------------------------------------------------------------------
  2332. ///
  2333. /// Instr::GetInsertBeforeByteCodeUsesInstr
  2334. /// Finds the instruction before which new instructions can be inserted, by skipping ByteCodeUses instructions associated with
  2335. /// this instruction.
  2336. ///
  2337. ///----------------------------------------------------------------------------
  2338. IR::Instr *Instr::GetInsertBeforeByteCodeUsesInstr()
  2339. {
  2340. const uint32 byteCodeOffset = GetByteCodeOffset();
  2341. IR::Instr *insertBeforeInstr = this;
  2342. IR::Instr *prevInstr = insertBeforeInstr->m_prev;
  2343. while(prevInstr && prevInstr->IsByteCodeUsesInstr() && prevInstr->GetByteCodeOffset() == byteCodeOffset)
  2344. {
  2345. insertBeforeInstr = prevInstr;
  2346. prevInstr = prevInstr->m_prev;
  2347. }
  2348. return insertBeforeInstr;
  2349. }
  2350. ///----------------------------------------------------------------------------
  2351. ///
  2352. /// Instr::GetOrCreateContinueLabel
  2353. ///
  2354. ///----------------------------------------------------------------------------
  2355. IR::LabelInstr *
  2356. Instr::GetOrCreateContinueLabel(const bool isHelper)
  2357. {
  2358. if(m_next && m_next->IsLabelInstr() && m_next->AsLabelInstr()->isOpHelper == isHelper)
  2359. {
  2360. return m_next->AsLabelInstr();
  2361. }
  2362. IR::LabelInstr *const label = IR::LabelInstr::New(Js::OpCode::Label, m_func, isHelper);
  2363. InsertAfter(label);
  2364. return label;
  2365. }
  2366. ///----------------------------------------------------------------------------
  2367. ///
  2368. /// Instr::FindRegUse
  2369. ///
  2370. /// Search a reg use of the given sym. Return the RegOpnd that uses it.
  2371. ///
  2372. ///----------------------------------------------------------------------------
  2373. IR::RegOpnd *
  2374. Instr::FindRegUse(StackSym *sym)
  2375. {
  2376. IR::Opnd *src1 = this->GetSrc1();
  2377. // Check src1
  2378. if (src1)
  2379. {
  2380. if (src1->IsRegOpnd())
  2381. {
  2382. RegOpnd *regOpnd = src1->AsRegOpnd();
  2383. if (regOpnd->m_sym == sym)
  2384. {
  2385. return regOpnd;
  2386. }
  2387. }
  2388. else if (src1->IsIndirOpnd())
  2389. {
  2390. IR::IndirOpnd *indirOpnd = src1->AsIndirOpnd();
  2391. if (indirOpnd->GetBaseOpnd()->m_sym == sym)
  2392. {
  2393. return indirOpnd->GetBaseOpnd();
  2394. }
  2395. else if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == sym)
  2396. {
  2397. return indirOpnd->GetIndexOpnd();
  2398. }
  2399. }
  2400. IR::Opnd *src2 = this->GetSrc2();
  2401. // Check src2
  2402. if (src2)
  2403. {
  2404. if (src2->IsRegOpnd())
  2405. {
  2406. RegOpnd *regOpnd = src2->AsRegOpnd();
  2407. if (regOpnd->m_sym == sym)
  2408. {
  2409. return regOpnd;
  2410. }
  2411. }
  2412. else if (src2->IsIndirOpnd())
  2413. {
  2414. IR::IndirOpnd *indirOpnd = src2->AsIndirOpnd();
  2415. if (indirOpnd->GetBaseOpnd()->m_sym == sym)
  2416. {
  2417. return indirOpnd->GetBaseOpnd();
  2418. }
  2419. else if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == sym)
  2420. {
  2421. return indirOpnd->GetIndexOpnd();
  2422. }
  2423. }
  2424. }
  2425. }
  2426. // Check uses in dst
  2427. IR::Opnd *dst = this->GetDst();
  2428. if (dst != nullptr && dst->IsIndirOpnd())
  2429. {
  2430. IR::IndirOpnd *indirOpnd = dst->AsIndirOpnd();
  2431. if (indirOpnd->GetBaseOpnd()->m_sym == sym)
  2432. {
  2433. return indirOpnd->GetBaseOpnd();
  2434. }
  2435. else if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == sym)
  2436. {
  2437. return indirOpnd->GetIndexOpnd();
  2438. }
  2439. }
  2440. return nullptr;
  2441. }
  2442. IR::RegOpnd *
  2443. Instr::FindRegUseInRange(StackSym *sym, IR::Instr *instrBegin, IR::Instr *instrEnd)
  2444. {
  2445. FOREACH_INSTR_IN_RANGE(instr, instrBegin, instrEnd)
  2446. {
  2447. Assert(instr);
  2448. IR::RegOpnd *opnd = instr->FindRegUse(sym);
  2449. if (opnd)
  2450. {
  2451. return opnd;
  2452. }
  2453. }
  2454. NEXT_INSTR_IN_RANGE;
  2455. return nullptr;
  2456. }
  2457. ///----------------------------------------------------------------------------
  2458. ///
  2459. /// Instr::FindRegDef
  2460. ///
  2461. /// Search a reg def of the given sym. Return the RegOpnd that defines it.
  2462. ///
  2463. ///----------------------------------------------------------------------------
  2464. IR::RegOpnd *
  2465. Instr::FindRegDef(StackSym *sym)
  2466. {
  2467. IR::Opnd *dst = this->GetDst();
  2468. if (dst)
  2469. {
  2470. if (dst->IsRegOpnd())
  2471. {
  2472. RegOpnd *regOpnd = dst->AsRegOpnd();
  2473. if (regOpnd->m_sym == sym)
  2474. {
  2475. return regOpnd;
  2476. }
  2477. }
  2478. }
  2479. return nullptr;
  2480. }
  2481. void
  2482. Instr::TransferDstAttributesTo(Instr * instr)
  2483. {
  2484. instr->dstIsTempNumber = this->dstIsTempNumber;
  2485. instr->dstIsTempNumberTransferred = this->dstIsTempNumberTransferred;
  2486. instr->dstIsTempObject = this->dstIsTempObject;
  2487. }
  2488. void
  2489. Instr::TransferTo(Instr * instr)
  2490. {
  2491. Assert(instr->m_dst == nullptr);
  2492. Assert(instr->m_src1 == nullptr);
  2493. Assert(instr->m_src2 == nullptr);
  2494. this->TransferDstAttributesTo(instr);
  2495. instr->usesStackArgumentsObject = this->usesStackArgumentsObject;
  2496. instr->isCloned = this->isCloned;
  2497. instr->ignoreNegativeZero = this->ignoreNegativeZero;
  2498. instr->ignoreIntOverflow = this->ignoreIntOverflow;
  2499. instr->ignoreIntOverflowInRange = this->ignoreIntOverflowInRange;
  2500. instr->ignoreOverflowBitCount = this->ignoreOverflowBitCount;
  2501. instr->loadedArrayHeadSegment = this->loadedArrayHeadSegment;
  2502. instr->loadedArrayHeadSegmentLength = this->loadedArrayHeadSegmentLength;
  2503. instr->extractedUpperBoundCheckWithoutHoisting = this->extractedUpperBoundCheckWithoutHoisting;
  2504. instr->m_number = this->m_number;
  2505. instr->m_src1 = this->m_src1;
  2506. instr->m_src2 = this->m_src2;
  2507. instr->dstIsAlwaysConvertedToInt32 = this->dstIsAlwaysConvertedToInt32;
  2508. instr->dstIsAlwaysConvertedToNumber = this->dstIsAlwaysConvertedToNumber;
  2509. IR::Opnd * dst = this->m_dst;
  2510. if (dst)
  2511. {
  2512. instr->m_dst = dst;
  2513. this->m_dst = nullptr;
  2514. if (dst->IsRegOpnd())
  2515. {
  2516. Sym * sym = dst->AsRegOpnd()->m_sym;
  2517. if (sym->IsStackSym() && sym->AsStackSym()->m_isSingleDef)
  2518. {
  2519. Assert(sym->AsStackSym()->m_instrDef == this);
  2520. StackSym * stackSym = sym->AsStackSym();
  2521. stackSym->m_instrDef = instr;
  2522. }
  2523. }
  2524. }
  2525. this->m_src1 = nullptr;
  2526. this->m_src2 = nullptr;
  2527. }
  2528. IR::Instr *
  2529. Instr::ConvertToBailOutInstr(IR::Instr * bailOutTarget, IR::BailOutKind kind)
  2530. {
  2531. Func * func = bailOutTarget->m_func;
  2532. BailOutInfo * bailOutInfo = JitAnew(func->m_alloc, BailOutInfo, bailOutTarget->GetByteCodeOffset(), func);
  2533. #if ENABLE_DEBUG_CONFIG_OPTIONS
  2534. bailOutInfo->bailOutOpcode = this->m_opcode;
  2535. #endif
  2536. return this->ConvertToBailOutInstr(bailOutInfo, kind);
  2537. }
  2538. // Notes:
  2539. // - useAuxBailout = true specifies that this bailout further will be invisible to globopt, etc, and we'll use auxBailoutKind instead of BailoutKind.
  2540. // Currently this is used for BailOutIgnoreException for debugger.
  2541. //
  2542. // Here's typical workflow for scenario useAuxBailout = true.
  2543. // - IRBuilder::Build calls this with kind == BailOutIgnoreException
  2544. // - In here we save the kind to auxBailOut and save bail out info but set hasBailOutInfo to false.
  2545. // - During globopt optimizations presence of this bail out is not detected and instrs can add/remove bailouts as they need.
  2546. // - If they call to convert this instr to bail out instr, we set bailOutKind to what they want and replace bailOutInfo.
  2547. // ** This assumes that for aux bail out bailoutInfo does not really matter (if its pre/post op, etc) **
  2548. // - This is the case for ignore exception.
  2549. // - This will cause to share aux bail out with regular bail out.
  2550. // - In globopt right after OptInstr we check if there is aux bail out which wasn't shared with regular bail out,
  2551. // and if it's not, we convert it back to regular bail out.
  2552. IR::Instr *
  2553. Instr::ConvertToBailOutInstr(BailOutInfo * bailOutInfo, IR::BailOutKind kind, bool useAuxBailOut /* = false */)
  2554. {
  2555. Assert(!this->HasBailOutInfo());
  2556. AssertMsg(!useAuxBailOut || !this->HasAuxBailOut(), "Already aux bail out!");
  2557. Assert(!this->HasAuxBailOut() || this->GetAuxBailOutKind() != IR::BailOutInvalid);
  2558. IR::Instr * bailOutInstr = nullptr;
  2559. if (this->HasAuxBailOut())
  2560. {
  2561. // This instr has already been converted to bailout instr. Only possible with aux bail out.
  2562. // Typical scenario is when globopt calls to convert to e.g. BailOutOnImplcitCalls for the instr which
  2563. // was already converted to bail out instr with HasBailOutInfo() == false and HasAuxBailOutInfo() == true,
  2564. // so that aux bail out is hidden in between IRBuilder and lowerer.
  2565. AssertMsg((this->GetAuxBailOutKind() & ~(IR::BailOutIgnoreException | IR::BailOutForceByFlag)) == 0, "Only IR::BailOutIgnoreException|ForceByFlag supported here.");
  2566. // What we rely on here is:
  2567. // - bailout doesn't have any args.
  2568. // - bailout doesn't use offset as we get it from DebuggingFlags at time of bailout.
  2569. // Use prev debugger bailout kind as decoration, while keeping new kind as main.
  2570. this->SetBailOutKind_NoAssert(kind);
  2571. // Clear old (aux) info and set to the new bailOutInfo.
  2572. this->ReplaceBailOutInfo(bailOutInfo);
  2573. bailOutInfo->bailOutInstr = this;
  2574. this->hasBailOutInfo = true;
  2575. bailOutInstr = this;
  2576. }
  2577. else
  2578. {
  2579. switch (this->m_kind)
  2580. {
  2581. case InstrKindInstr:
  2582. bailOutInstr = IR::BailOutInstr::New(this->m_opcode, kind, bailOutInfo, bailOutInfo->bailOutFunc);
  2583. break;
  2584. case InstrKindProfiled:
  2585. bailOutInstr = IR::ProfiledBailOutInstr::New(this->m_opcode, kind, bailOutInfo, bailOutInfo->bailOutFunc);
  2586. bailOutInstr->AsProfiledInstr()->u = this->AsProfiledInstr()->u;
  2587. break;
  2588. case InstrKindBranch:
  2589. {
  2590. IR::BranchInstr * branchInstr = this->AsBranchInstr();
  2591. Assert(!branchInstr->IsMultiBranch());
  2592. IR::BranchBailOutInstr * branchBailOutInstr = IR::BranchBailOutInstr::New(this->m_opcode, kind, bailOutInfo, bailOutInfo->bailOutFunc);
  2593. branchBailOutInstr->SetTarget(branchInstr->GetTarget());
  2594. branchBailOutInstr->SetByteCodeReg(branchInstr->GetByteCodeReg());
  2595. bailOutInstr = branchBailOutInstr;
  2596. break;
  2597. }
  2598. default:
  2599. AnalysisAssert(false);
  2600. };
  2601. this->m_next->m_prev = bailOutInstr;
  2602. this->m_prev->m_next = bailOutInstr;
  2603. bailOutInstr->m_next = this->m_next;
  2604. bailOutInstr->m_prev = this->m_prev;
  2605. this->TransferTo(bailOutInstr);
  2606. this->Free();
  2607. }
  2608. if (useAuxBailOut)
  2609. {
  2610. // Move bail out kind from bailOutKind to auxBailOutKind and hide bailOutInfo as if this is not a bail out instr.
  2611. bailOutInstr->SetAuxBailOutKind(kind);
  2612. bailOutInstr->SetBailOutKind_NoAssert(IR::BailOutInvalid);
  2613. bailOutInstr->hasBailOutInfo = false;
  2614. bailOutInstr->hasAuxBailOut = true;
  2615. }
  2616. return bailOutInstr;
  2617. }
  2618. // Convert aux bailout to regular bail out.
  2619. // Called by globopt after all optimizations are done, in case we still have aux bail out on the instr.
  2620. void Instr::PromoteAuxBailOut()
  2621. {
  2622. Assert(!this->HasBailOutInfo());
  2623. Assert(this->GetAuxBailOutKind() != IR::BailOutInvalid);
  2624. this->SetBailOutKind_NoAssert(this->GetAuxBailOutKind());
  2625. this->SetAuxBailOutKind(IR::BailOutInvalid);
  2626. this->hasBailOutInfo = true;
  2627. this->hasAuxBailOut = false;
  2628. }
  2629. // Reset all tracks of aux bailout but don't rest the bail out info.
  2630. // Used after we extract aux bail out in lowerer.
  2631. void Instr::ResetAuxBailOut()
  2632. {
  2633. this->SetAuxBailOutKind(IR::BailOutInvalid);
  2634. this->hasAuxBailOut = false;
  2635. }
  2636. void
  2637. Instr::ClearBailOutInfo()
  2638. {
  2639. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  2640. {
  2641. BailOutInfo * bailOutInfo = this->GetBailOutInfo();
  2642. Assert(bailOutInfo);
  2643. if (bailOutInfo->bailOutInstr == this)
  2644. {
  2645. JitArenaAllocator * alloc = this->m_func->m_alloc;
  2646. bailOutInfo->Clear(alloc);
  2647. JitAdelete(alloc, bailOutInfo);
  2648. }
  2649. this->hasBailOutInfo = false;
  2650. this->hasAuxBailOut = false;
  2651. }
  2652. }
  2653. bool Instr::CanHaveArgOutChain() const
  2654. {
  2655. return
  2656. this->m_opcode == Js::OpCode::CallI ||
  2657. this->m_opcode == Js::OpCode::CallIFixed ||
  2658. this->m_opcode == Js::OpCode::NewScObject ||
  2659. this->m_opcode == Js::OpCode::NewScObjectSpread ||
  2660. this->m_opcode == Js::OpCode::NewScObjArray ||
  2661. this->m_opcode == Js::OpCode::NewScObjArraySpread;
  2662. }
  2663. bool Instr::HasEmptyArgOutChain(IR::Instr** startCallInstrOut)
  2664. {
  2665. Assert(CanHaveArgOutChain());
  2666. if (GetSrc2()->IsRegOpnd())
  2667. {
  2668. IR::RegOpnd * argLinkOpnd = GetSrc2()->AsRegOpnd();
  2669. StackSym *argLinkSym = argLinkOpnd->m_sym->AsStackSym();
  2670. AssertMsg(!argLinkSym->IsArgSlotSym() && argLinkSym->m_isSingleDef, "Arg tree not single def...");
  2671. IR::Instr* startCallInstr = argLinkSym->m_instrDef;
  2672. AssertMsg(startCallInstr->m_opcode == Js::OpCode::StartCall, "Problem with arg chain.");
  2673. if (startCallInstrOut != nullptr)
  2674. {
  2675. *startCallInstrOut = startCallInstr;
  2676. }
  2677. return true;
  2678. }
  2679. return false;
  2680. }
  2681. bool Instr::HasFixedFunctionAddressTarget() const
  2682. {
  2683. Assert(
  2684. this->m_opcode == Js::OpCode::CallI ||
  2685. this->m_opcode == Js::OpCode::CallIFixed ||
  2686. this->m_opcode == Js::OpCode::NewScObject ||
  2687. this->m_opcode == Js::OpCode::NewScObjectSpread ||
  2688. this->m_opcode == Js::OpCode::NewScObjArray ||
  2689. this->m_opcode == Js::OpCode::NewScObjArraySpread ||
  2690. this->m_opcode == Js::OpCode::NewScObjectNoCtor);
  2691. return
  2692. this->GetSrc1() != nullptr &&
  2693. this->GetSrc1()->IsAddrOpnd() &&
  2694. this->GetSrc1()->AsAddrOpnd()->GetAddrOpndKind() == IR::AddrOpndKind::AddrOpndKindDynamicVar &&
  2695. this->GetSrc1()->AsAddrOpnd()->m_isFunction;
  2696. }
  2697. void Instr::MoveArgs(bool generateByteCodeCapture)
  2698. {
  2699. Assert(this->m_opcode == Js::OpCode::InlineeStart || this->m_opcode == Js::OpCode::CallDirect ||
  2700. this->m_opcode == Js::OpCode::CallI || this->m_opcode == Js::OpCode::CallIFixed);
  2701. IR::Instr *argInsertInstr = this;
  2702. this->IterateArgInstrs([&](IR::Instr* argInstr)
  2703. {
  2704. if (generateByteCodeCapture)
  2705. {
  2706. argInstr->GenerateBytecodeArgOutCapture();
  2707. }
  2708. argInstr->Move(argInsertInstr);
  2709. argInsertInstr = argInstr;
  2710. return false;
  2711. });
  2712. }
  2713. void Instr::Move(IR::Instr* insertInstr)
  2714. {
  2715. this->Unlink();
  2716. this->ClearByteCodeOffset();
  2717. this->SetByteCodeOffset(insertInstr);
  2718. insertInstr->InsertBefore(this);
  2719. }
  2720. IR::Instr* Instr::GetBytecodeArgOutCapture()
  2721. {
  2722. Assert(this->m_opcode == Js::OpCode::ArgOut_A_Inline ||
  2723. this->m_opcode == Js::OpCode::ArgOut_A ||
  2724. this->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  2725. Assert(this->m_dst->GetStackSym()->m_isArgCaptured);
  2726. IR::Instr* instr = this->GetSrc1()->GetStackSym()->m_instrDef;
  2727. Assert(instr->m_opcode == Js::OpCode::BytecodeArgOutCapture);
  2728. return instr;
  2729. }
  2730. bool Instr::HasByteCodeArgOutCapture()
  2731. {
  2732. Assert(this->m_opcode == Js::OpCode::ArgOut_A_FixupForStackArgs ||
  2733. this->m_opcode == Js::OpCode::ArgOut_A_Inline ||
  2734. this->m_opcode == Js::OpCode::ArgOut_A ||
  2735. this->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn ||
  2736. this->m_opcode == Js::OpCode::ArgOut_A_FromStackArgs);
  2737. if (this->m_dst->GetStackSym()->m_isArgCaptured)
  2738. {
  2739. Assert(GetBytecodeArgOutCapture() != nullptr);
  2740. return true;
  2741. }
  2742. return false;
  2743. }
  2744. void Instr::GenerateBytecodeArgOutCapture()
  2745. {
  2746. if (!HasByteCodeArgOutCapture())
  2747. {
  2748. this->m_dst->GetStackSym()->m_isArgCaptured = true;
  2749. StackSym* tmpSym = StackSym::NewArgSlotRegSym(this->GetDst()->GetStackSym()->GetArgSlotNum(), this->m_func, this->GetDst()->GetType());
  2750. IR::Instr* instr = this->HoistSrc1(Js::OpCode::BytecodeArgOutCapture, RegNOREG, tmpSym);
  2751. instr->SetByteCodeOffset(this);
  2752. }
  2753. }
  2754. void Instr::GenerateArgOutSnapshot()
  2755. {
  2756. StackSym* tmpSym = StackSym::NewArgSlotRegSym(this->GetDst()->GetStackSym()->GetArgSlotNum(), this->m_func);
  2757. IR::Instr* instr = this->HoistSrc1(Js::OpCode::Ld_A, RegNOREG, tmpSym);
  2758. instr->SetByteCodeOffset(this);
  2759. }
  2760. IR::Instr* Instr::GetArgOutSnapshot()
  2761. {
  2762. Assert(this->m_opcode == Js::OpCode::ArgOut_A_FixupForStackArgs);
  2763. IR::Instr* instr = this->GetSrc1()->GetStackSym()->m_instrDef;
  2764. Assert(instr->m_opcode == Js::OpCode::Ld_A);
  2765. return instr;
  2766. }
  2767. bool Instr::HasAnyImplicitCalls() const
  2768. {
  2769. // there can be no implicit calls in asm.js
  2770. if (m_func->GetJnFunction()->GetIsAsmjsMode())
  2771. {
  2772. return false;
  2773. }
  2774. if (OpCodeAttr::HasImplicitCall(this->m_opcode))
  2775. {
  2776. return true;
  2777. }
  2778. if (OpCodeAttr::CallsValueOf(this->m_opcode))
  2779. {
  2780. IR::Opnd *src1 = this->GetSrc1();
  2781. if (src1)
  2782. {
  2783. if (!src1->GetValueType().IsPrimitive())
  2784. {
  2785. return true;
  2786. }
  2787. IR::Opnd *src2 = this->GetSrc2();
  2788. if(src2 && !src2->GetValueType().IsPrimitive())
  2789. {
  2790. return true;
  2791. }
  2792. }
  2793. }
  2794. return false;
  2795. }
  2796. bool Instr::HasAnySideEffects() const
  2797. {
  2798. if (OpCodeAttr::HasSideEffects(this->m_opcode))
  2799. {
  2800. return true;
  2801. }
  2802. if (this->HasAnyImplicitCalls())
  2803. {
  2804. return true;
  2805. }
  2806. return false;
  2807. }
  2808. Js::JavascriptFunction* Instr::GetFixedFunction() const
  2809. {
  2810. Assert(HasFixedFunctionAddressTarget());
  2811. Js::JavascriptFunction* function = Js::JavascriptFunction::FromVar(this->m_src1->AsAddrOpnd()->m_address);
  2812. return function;
  2813. }
  2814. IR::Instr* Instr::GetNextArg()
  2815. {
  2816. Assert(this->m_opcode == Js::OpCode::ArgOut_A_FixupForStackArgs ||
  2817. this->m_opcode == Js::OpCode::ArgOut_A_Inline ||
  2818. this->m_opcode == Js::OpCode::ArgOut_A ||
  2819. this->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn ||
  2820. this->m_opcode == Js::OpCode::InlineeStart);
  2821. IR::Instr* argInstr = this;
  2822. while (true)
  2823. {
  2824. StackSym* linkSym;
  2825. if (argInstr->GetSrc2()->IsRegOpnd())
  2826. {
  2827. linkSym = argInstr->GetSrc2()->AsRegOpnd()->m_sym->AsStackSym();
  2828. }
  2829. else
  2830. {
  2831. linkSym = argInstr->GetSrc2()->AsSymOpnd()->m_sym->AsStackSym();
  2832. Assert(linkSym->IsArgSlotSym());
  2833. }
  2834. Assert(linkSym->IsSingleDef());
  2835. argInstr = linkSym->m_instrDef;
  2836. if (argInstr->m_opcode == Js::OpCode::ArgOut_A_InlineSpecialized)
  2837. {
  2838. continue;
  2839. }
  2840. if (argInstr->m_opcode == Js::OpCode::StartCall)
  2841. {
  2842. break;
  2843. }
  2844. return argInstr;
  2845. }
  2846. return nullptr;
  2847. }
  2848. uint Instr::GetArgOutCount(bool getInterpreterArgOutCount)
  2849. {
  2850. // There are cases of inlining like .apply and .call target inlining, where we muck around with the ArgOut sequence,
  2851. // and make it different from the one the interpreter sees (and expects, on a bailout).
  2852. // In such cases, we set the interpreter version of the number of ArgOuts as the src2 of StartCall,
  2853. // and any code that queries the argout count for bailout purposes should look at the src2 (if available) of these instructions.
  2854. // If the src2 is not set, that means that the interpreter and the JIT versions of the argout count are the same.
  2855. Js::OpCode opcode = this->m_opcode;
  2856. Assert(opcode == Js::OpCode::StartCall ||
  2857. opcode == Js::OpCode::InlineeEnd || opcode == Js::OpCode::InlineBuiltInEnd|| opcode == Js::OpCode::InlineNonTrackingBuiltInEnd ||
  2858. opcode == Js::OpCode::EndCallForPolymorphicInlinee || opcode == Js::OpCode::LoweredStartCall);
  2859. if (!getInterpreterArgOutCount)
  2860. {
  2861. return this->GetSrc1()->AsIntConstOpnd()->AsUint32();
  2862. }
  2863. Assert(opcode == Js::OpCode::StartCall);
  2864. IntConstType argOutCount = !this->GetSrc2() ? this->GetSrc1()->AsIntConstOpnd()->GetValue() : this->GetSrc2()->AsIntConstOpnd()->GetValue();
  2865. Assert(argOutCount >= 0 && argOutCount < UINT32_MAX);
  2866. return (uint)argOutCount;
  2867. }
  2868. PropertySymOpnd *Instr::GetPropertySymOpnd() const
  2869. {
  2870. if (m_src1 && m_src1->IsSymOpnd() && m_src1->AsSymOpnd()->IsPropertySymOpnd())
  2871. {
  2872. return m_src1->AsPropertySymOpnd();
  2873. }
  2874. if (m_dst && m_dst->IsSymOpnd() && m_dst->AsSymOpnd()->IsPropertySymOpnd())
  2875. {
  2876. return m_dst->AsPropertySymOpnd();
  2877. }
  2878. return nullptr;
  2879. }
  2880. bool Instr::CallsAccessor(IR::PropertySymOpnd* methodOpnd)
  2881. {
  2882. if (methodOpnd)
  2883. {
  2884. Assert(methodOpnd->HasObjTypeSpecFldInfo());
  2885. return methodOpnd->UsesAccessor();
  2886. }
  2887. return CallsGetter() || CallsSetter();
  2888. }
  2889. bool Instr::CallsSetter(IR::PropertySymOpnd* methodOpnd)
  2890. {
  2891. return
  2892. this->IsProfiledInstr() &&
  2893. (this->m_dst && this->m_dst->IsSymOpnd() && this->m_dst->AsSymOpnd()->IsPropertySymOpnd()) &&
  2894. ((this->AsProfiledInstr()->u.FldInfo().flags & Js::FldInfo_FromAccessor) != 0);
  2895. }
  2896. bool Instr::CallsGetter(IR::PropertySymOpnd* methodOpnd)
  2897. {
  2898. return
  2899. this->IsProfiledInstr() &&
  2900. (this->m_src1 && this->m_src1->IsSymOpnd() && this->m_src1->AsSymOpnd()->IsPropertySymOpnd()) &&
  2901. ((this->AsProfiledInstr()->u.FldInfo().flags & Js::FldInfo_FromAccessor) != 0);
  2902. }
  2903. IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, Js::Var varConst, Func* func)
  2904. {
  2905. IR::Opnd *srcOpnd = nullptr;
  2906. IR::Instr *instr;
  2907. if (Js::TaggedInt::Is(varConst))
  2908. {
  2909. IntConstType value = Js::TaggedInt::ToInt32(varConst);
  2910. instr = IR::Instr::New(Js::OpCode::LdC_A_I4, dstOpnd, IR::IntConstOpnd::New(value, TyInt32, func), func);
  2911. if (dstOpnd->m_sym->IsSingleDef())
  2912. {
  2913. dstOpnd->m_sym->SetIsIntConst(value);
  2914. }
  2915. }
  2916. else
  2917. {
  2918. Js::RecyclableObject *obj;
  2919. if (varConst == (Js::Var)&Js::NullFrameDisplay)
  2920. {
  2921. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd,
  2922. IR::AddrOpnd::New((Js::Var)&Js::NullFrameDisplay, IR::AddrOpndKindDynamicMisc, func), func);
  2923. }
  2924. else if (varConst == (Js::Var)&Js::StrictNullFrameDisplay)
  2925. {
  2926. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd,
  2927. IR::AddrOpnd::New((Js::Var)&Js::StrictNullFrameDisplay, IR::AddrOpndKindDynamicMisc, func), func);
  2928. }
  2929. else
  2930. {
  2931. ValueType valueType;
  2932. switch (Js::JavascriptOperators::GetTypeId(varConst))
  2933. {
  2934. case Js::TypeIds_String:
  2935. {
  2936. obj = Js::RecyclableObject::FromVar(varConst);
  2937. srcOpnd = IR::AddrOpnd::New(obj, IR::AddrOpndKindDynamicVar, func, true);
  2938. instr = IR::Instr::New(Js::OpCode::LdStr, dstOpnd, srcOpnd, func);
  2939. Assert(dstOpnd->m_sym->m_isSingleDef);
  2940. if (dstOpnd->m_sym->IsSingleDef())
  2941. {
  2942. dstOpnd->m_sym->m_isStrConst = true;
  2943. dstOpnd->m_sym->m_isConst = true;
  2944. }
  2945. dstOpnd->SetValueType(ValueType::String);
  2946. srcOpnd->SetValueType(ValueType::String);
  2947. break;
  2948. }
  2949. case Js::TypeIds_Number:
  2950. {
  2951. Assert(Js::JavascriptNumber::Is(varConst));
  2952. srcOpnd = IR::FloatConstOpnd::New(varConst, TyFloat64, func);
  2953. instr = IR::Instr::New(Js::OpCode::LdC_A_R8, dstOpnd, srcOpnd, func);
  2954. if (dstOpnd->m_sym->IsSingleDef())
  2955. {
  2956. dstOpnd->m_sym->SetIsFloatConst();
  2957. #if FLOATVAR
  2958. dstOpnd->m_sym->m_isNotInt = FALSE;
  2959. #else
  2960. // Don't set m_isNotInt to true if the float constant value is an int32 or uint32. Uint32s may sometimes be
  2961. // treated as int32s for the purposes of int specialization.
  2962. dstOpnd->m_sym->m_isNotInt = !Js::JavascriptNumber::IsInt32OrUInt32_NoChecks(varConst);
  2963. #endif
  2964. }
  2965. break;
  2966. }
  2967. case Js::TypeIds_Undefined:
  2968. valueType = ValueType::Undefined;
  2969. goto dynamicVar;
  2970. case Js::TypeIds_Null:
  2971. valueType = ValueType::Null;
  2972. goto dynamicVar;
  2973. case Js::TypeIds_Boolean:
  2974. valueType = ValueType::Boolean;
  2975. goto dynamicVar;
  2976. default:
  2977. valueType = ValueType::GetObject(ObjectType::Object);
  2978. dynamicVar:
  2979. obj = Js::RecyclableObject::FromVar(varConst);
  2980. srcOpnd = IR::AddrOpnd::New(obj, IR::AddrOpndKindDynamicVar, func, true);
  2981. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, func);
  2982. if (dstOpnd->m_sym->IsSingleDef())
  2983. {
  2984. dstOpnd->m_sym->m_isConst = true;
  2985. }
  2986. dstOpnd->SetValueType(valueType);
  2987. srcOpnd->SetValueType(valueType);
  2988. break;
  2989. }
  2990. }
  2991. }
  2992. return instr;
  2993. }
  2994. bool Instr::UsesAllFields()
  2995. {
  2996. return OpCodeAttr::UseAllFields(this->m_opcode) || this->CallsAccessor();
  2997. }
  2998. BranchInstr *
  2999. Instr::ChangeCmCCToBranchInstr(LabelInstr *targetInstr)
  3000. {
  3001. Js::OpCode newOpcode;
  3002. switch (this->m_opcode)
  3003. {
  3004. case Js::OpCode::CmEq_A:
  3005. newOpcode = Js::OpCode::BrEq_A;
  3006. break;
  3007. case Js::OpCode::CmGe_A:
  3008. newOpcode = Js::OpCode::BrGe_A;
  3009. break;
  3010. case Js::OpCode::CmGt_A:
  3011. newOpcode = Js::OpCode::BrGt_A;
  3012. break;
  3013. case Js::OpCode::CmLt_A:
  3014. newOpcode = Js::OpCode::BrLt_A;
  3015. break;
  3016. case Js::OpCode::CmLe_A:
  3017. newOpcode = Js::OpCode::BrLe_A;
  3018. break;
  3019. case Js::OpCode::CmUnGe_A:
  3020. newOpcode = Js::OpCode::BrUnGe_A;
  3021. break;
  3022. case Js::OpCode::CmUnGt_A:
  3023. newOpcode = Js::OpCode::BrUnGt_A;
  3024. break;
  3025. case Js::OpCode::CmUnLt_A:
  3026. newOpcode = Js::OpCode::BrUnLt_A;
  3027. break;
  3028. case Js::OpCode::CmUnLe_A:
  3029. newOpcode = Js::OpCode::BrUnLe_A;
  3030. break;
  3031. case Js::OpCode::CmNeq_A:
  3032. newOpcode = Js::OpCode::BrNeq_A;
  3033. break;
  3034. case Js::OpCode::CmSrEq_A:
  3035. newOpcode = Js::OpCode::BrSrEq_A;
  3036. break;
  3037. case Js::OpCode::CmSrNeq_A:
  3038. newOpcode = Js::OpCode::BrSrNeq_A;
  3039. break;
  3040. case Js::OpCode::CmEq_I4:
  3041. newOpcode = Js::OpCode::BrEq_I4;
  3042. break;
  3043. case Js::OpCode::CmGe_I4:
  3044. newOpcode = Js::OpCode::BrGe_I4;
  3045. break;
  3046. case Js::OpCode::CmGt_I4:
  3047. newOpcode = Js::OpCode::BrGt_I4;
  3048. break;
  3049. case Js::OpCode::CmLt_I4:
  3050. newOpcode = Js::OpCode::BrLt_I4;
  3051. break;
  3052. case Js::OpCode::CmLe_I4:
  3053. newOpcode = Js::OpCode::BrLe_I4;
  3054. break;
  3055. case Js::OpCode::CmUnGe_I4:
  3056. newOpcode = Js::OpCode::BrUnGe_I4;
  3057. break;
  3058. case Js::OpCode::CmUnGt_I4:
  3059. newOpcode = Js::OpCode::BrUnGt_I4;
  3060. break;
  3061. case Js::OpCode::CmUnLt_I4:
  3062. newOpcode = Js::OpCode::BrUnLt_I4;
  3063. break;
  3064. case Js::OpCode::CmUnLe_I4:
  3065. newOpcode = Js::OpCode::BrUnLe_I4;
  3066. break;
  3067. case Js::OpCode::CmNeq_I4:
  3068. newOpcode = Js::OpCode::BrNeq_I4;
  3069. break;
  3070. default:
  3071. Assert(UNREACHED);
  3072. __assume(UNREACHED);
  3073. }
  3074. BranchInstr *instrBr = BranchInstr::New(newOpcode, targetInstr, this->m_func);
  3075. this->InsertBefore(instrBr);
  3076. instrBr->SetByteCodeOffset(this);
  3077. instrBr->SetSrc1(this->UnlinkSrc1());
  3078. instrBr->SetSrc2(this->UnlinkSrc2());
  3079. this->Remove();
  3080. return instrBr;
  3081. }
  3082. bool Instr::IsCmCC_A()
  3083. {
  3084. return (this->m_opcode >= Js::OpCode::CmEq_A && this->m_opcode <= Js::OpCode::CmSrNeq_A) && this->GetSrc1()->IsVar();
  3085. }
  3086. bool Instr::IsCmCC_R8()
  3087. {
  3088. return (this->m_opcode >= Js::OpCode::CmEq_A && this->m_opcode <= Js::OpCode::CmSrNeq_A) && this->GetSrc1()->IsFloat64();
  3089. }
  3090. bool Instr::IsCmCC_I4()
  3091. {
  3092. return (this->m_opcode >= Js::OpCode::CmEq_I4 && this->m_opcode <= Js::OpCode::CmUnGe_I4);
  3093. }
  3094. bool Instr::BinaryCalculator(IntConstType src1Const, IntConstType src2Const, IntConstType *pResult)
  3095. {
  3096. IntConstType value = 0;
  3097. switch (this->m_opcode)
  3098. {
  3099. case Js::OpCode::Add_A:
  3100. if (IntConstMath::Add(src1Const, src2Const, &value))
  3101. {
  3102. return false;
  3103. }
  3104. break;
  3105. case Js::OpCode::Sub_A:
  3106. if (IntConstMath::Sub(src1Const, src2Const, &value))
  3107. {
  3108. return false;
  3109. }
  3110. break;
  3111. case Js::OpCode::Mul_A:
  3112. if (IntConstMath::Mul(src1Const, src2Const, &value))
  3113. {
  3114. return false;
  3115. }
  3116. if (value == 0)
  3117. {
  3118. // might be -0
  3119. // Bail for now...
  3120. return false;
  3121. }
  3122. break;
  3123. case Js::OpCode::Div_A:
  3124. if (src2Const == 0)
  3125. {
  3126. // Could fold to INF/-INF
  3127. // instr->HoistSrc1(Js::OpCode::Ld_A);
  3128. return false;
  3129. }
  3130. if (src1Const == 0 && src2Const < 0)
  3131. {
  3132. // folds to -0. Bail for now...
  3133. return false;
  3134. }
  3135. if (IntConstMath::Div(src1Const, src2Const, &value))
  3136. {
  3137. return false;
  3138. }
  3139. if (src1Const % src2Const != 0)
  3140. {
  3141. // Bail for now...
  3142. return false;
  3143. }
  3144. break;
  3145. case Js::OpCode::Rem_A:
  3146. if (src2Const == 0)
  3147. {
  3148. // Bail for now...
  3149. return false;
  3150. }
  3151. if (IntConstMath::Mod(src1Const, src2Const, &value))
  3152. {
  3153. return false;
  3154. }
  3155. if (value == 0)
  3156. {
  3157. // might be -0
  3158. // Bail for now...
  3159. return false;
  3160. }
  3161. break;
  3162. case Js::OpCode::Shl_A:
  3163. // We don't care about overflow here
  3164. IntConstMath::Shl(src1Const, src2Const & 0x1F, &value);
  3165. break;
  3166. case Js::OpCode::Shr_A:
  3167. // We don't care about overflow here, and there shouldn't be any
  3168. IntConstMath::Shr(src1Const, src2Const & 0x1F, &value);
  3169. break;
  3170. case Js::OpCode::ShrU_A:
  3171. // We don't care about overflow here, and there shouldn't be any
  3172. IntConstMath::ShrU(src1Const, src2Const & 0x1F, &value);
  3173. if (value < 0)
  3174. {
  3175. // ShrU produces a UInt32. If it doesn't fit in a Int32, bail as we don't
  3176. // track signs of int values.
  3177. return false;
  3178. }
  3179. break;
  3180. case Js::OpCode::And_A:
  3181. // We don't care about overflow here, and there shouldn't be any
  3182. IntConstMath::And(src1Const, src2Const, &value);
  3183. break;
  3184. case Js::OpCode::Or_A:
  3185. // We don't care about overflow here, and there shouldn't be any
  3186. IntConstMath::Or(src1Const, src2Const, &value);
  3187. break;
  3188. case Js::OpCode::Xor_A:
  3189. // We don't care about overflow here, and there shouldn't be any
  3190. IntConstMath::Xor(src1Const, src2Const, &value);
  3191. break;
  3192. case Js::OpCode::InlineMathMin:
  3193. value = src1Const < src2Const ? src1Const : src2Const;
  3194. break;
  3195. case Js::OpCode::InlineMathMax:
  3196. value = src1Const > src2Const ? src1Const : src2Const;
  3197. break;
  3198. default:
  3199. return false;
  3200. }
  3201. *pResult = value;
  3202. return true;
  3203. }
  3204. bool Instr::UnaryCalculator(IntConstType src1Const, IntConstType *pResult)
  3205. {
  3206. IntConstType value = 0;
  3207. switch (this->m_opcode)
  3208. {
  3209. case Js::OpCode::Neg_A:
  3210. if (src1Const == 0)
  3211. {
  3212. // Could fold to -0.0
  3213. return false;
  3214. }
  3215. if (IntConstMath::Neg(src1Const, &value))
  3216. {
  3217. return false;
  3218. }
  3219. break;
  3220. case Js::OpCode::Not_A:
  3221. IntConstMath::Not(src1Const, &value);
  3222. break;
  3223. case Js::OpCode::Ld_A:
  3224. if (this->HasBailOutInfo())
  3225. {
  3226. Assert(this->GetBailOutKind() == IR::BailOutExpectingInteger);
  3227. this->ClearBailOutInfo();
  3228. }
  3229. value = src1Const;
  3230. break;
  3231. case Js::OpCode::Conv_Num:
  3232. case Js::OpCode::LdC_A_I4:
  3233. value = src1Const;
  3234. break;
  3235. case Js::OpCode::Incr_A:
  3236. if (IntConstMath::Inc(src1Const, &value))
  3237. {
  3238. return false;
  3239. }
  3240. break;
  3241. case Js::OpCode::Decr_A:
  3242. if (IntConstMath::Dec(src1Const, &value))
  3243. {
  3244. return false;
  3245. }
  3246. break;
  3247. case Js::OpCode::InlineMathAbs:
  3248. if (src1Const == IntConstMin)
  3249. {
  3250. return false;
  3251. }
  3252. else
  3253. {
  3254. value = src1Const < 0 ? -src1Const : src1Const;
  3255. }
  3256. break;
  3257. case Js::OpCode::InlineMathClz32:
  3258. DWORD clz;
  3259. DWORD src1Const32;
  3260. src1Const32 = (DWORD)src1Const;
  3261. if (_BitScanReverse(&clz, src1Const32))
  3262. {
  3263. value = 31 - clz;
  3264. }
  3265. else
  3266. {
  3267. value = 32;
  3268. }
  3269. this->ClearBailOutInfo();
  3270. break;
  3271. case Js::OpCode::InlineMathFloor:
  3272. value = src1Const;
  3273. this->ClearBailOutInfo();
  3274. break;
  3275. case Js::OpCode::InlineMathCeil:
  3276. value = src1Const;
  3277. this->ClearBailOutInfo();
  3278. break;
  3279. case Js::OpCode::InlineMathRound:
  3280. value = src1Const;
  3281. this->ClearBailOutInfo();
  3282. break;
  3283. case Js::OpCode::ToVar:
  3284. if (Js::TaggedInt::IsOverflow(src1Const))
  3285. {
  3286. return false;
  3287. }
  3288. else
  3289. {
  3290. value = src1Const;
  3291. this->ClearBailOutInfo();
  3292. break;
  3293. }
  3294. default:
  3295. return false;
  3296. }
  3297. *pResult = value;
  3298. return true;
  3299. }
  3300. #if ENABLE_DEBUG_CONFIG_OPTIONS
  3301. ///----------------------------------------------------------------------------
  3302. ///
  3303. /// Instr::DumpTestTrace
  3304. ///
  3305. /// Dump this instr in TestTrace.
  3306. ///
  3307. ///----------------------------------------------------------------------------
  3308. void
  3309. Instr::DumpTestTrace()
  3310. {
  3311. Output::Print(L"opcode: %s ", Js::OpCodeUtil::GetOpCodeName(m_opcode));
  3312. SymOpnd * symOpnd;
  3313. if (this->m_opcode == Js::OpCode::NewScFunc || this->m_opcode == Js::OpCode::NewScGenFunc)
  3314. {
  3315. Output::Print(L"\n");
  3316. return;
  3317. }
  3318. Opnd * src1 = this->GetSrc1();
  3319. if (!src1)
  3320. {
  3321. Output::Print(L"\n");
  3322. return;
  3323. }
  3324. if (src1->GetKind() != OpndKindSym)
  3325. {
  3326. Output::Print(L"\n");
  3327. return;
  3328. }
  3329. symOpnd = src1->AsSymOpnd();
  3330. if (symOpnd->m_sym->IsPropertySym())
  3331. {
  3332. PropertySym *propertySym = symOpnd->m_sym->AsPropertySym();
  3333. switch (propertySym->m_fieldKind)
  3334. {
  3335. case PropertyKindData:
  3336. {
  3337. Js::ScriptContext* scriptContext;
  3338. scriptContext = propertySym->GetFunc()->GetScriptContext();
  3339. Js::PropertyRecord const* fieldName = scriptContext->GetPropertyNameLocked(propertySym->m_propertyId);
  3340. Output::Print(L"field: %s ", fieldName->GetBuffer());
  3341. break;
  3342. }
  3343. case PropertyKindSlots:
  3344. Output::Print(L"field: [%d] ", propertySym->m_propertyId);
  3345. break;
  3346. case PropertyKindLocalSlots:
  3347. Output::Print(L"field: l[%d] ", propertySym->m_propertyId);
  3348. break;
  3349. default:
  3350. break;
  3351. }
  3352. Output::Print(L"\n");
  3353. }
  3354. }
  3355. ///----------------------------------------------------------------------------
  3356. ///
  3357. /// Instr::DumpFieldCopyPropTestTrace
  3358. ///
  3359. /// Dump fieldcopyprop when testtrace is enabled.
  3360. ///
  3361. ///----------------------------------------------------------------------------
  3362. void
  3363. Instr::DumpFieldCopyPropTestTrace()
  3364. {
  3365. switch (m_opcode)
  3366. {
  3367. case Js::OpCode::LdSlot:
  3368. case Js::OpCode::LdSlotArr:
  3369. case Js::OpCode::LdFld:
  3370. case Js::OpCode::LdFldForTypeOf:
  3371. case Js::OpCode::LdRootFld:
  3372. case Js::OpCode::LdRootFldForTypeOf:
  3373. case Js::OpCode::LdMethodFld:
  3374. case Js::OpCode::LdRootMethodFld:
  3375. case Js::OpCode::LdMethodFromFlags:
  3376. case Js::OpCode::ScopedLdMethodFld:
  3377. case Js::OpCode::TypeofElem:
  3378. wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  3379. Output::Print(L"TestTrace fieldcopyprop: function %s (%s) ", this->m_func->GetJnFunction()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
  3380. if (this->IsInlined())
  3381. {
  3382. Js::FunctionBody* topFunctionBody = this->m_func->GetTopFunc()->GetJnFunction();
  3383. Output::Print(L"inlined caller function %s (%s) ", topFunctionBody->GetDisplayName(), topFunctionBody->GetDebugNumberSet(debugStringBuffer));
  3384. }
  3385. this->DumpTestTrace();
  3386. default:
  3387. break;
  3388. }
  3389. }
  3390. #endif
  3391. #if ENABLE_DEBUG_CONFIG_OPTIONS
  3392. const char *
  3393. Instr::GetBailOutKindName() const
  3394. {
  3395. IR::BailOutKind kind = (IR::BailOutKind)0;
  3396. if (this->HasBailOutInfo())
  3397. {
  3398. kind |= this->GetBailOutKind();
  3399. }
  3400. if (this->HasAuxBailOut())
  3401. {
  3402. kind |= this->GetAuxBailOutKind();
  3403. }
  3404. return ::GetBailOutKindName(kind);
  3405. }
  3406. #endif
  3407. //
  3408. // Debug dumpers
  3409. //
  3410. #if DBG_DUMP
  3411. void
  3412. Instr::DumpByteCodeOffset()
  3413. {
  3414. if (m_func->HasByteCodeOffset())
  3415. {
  3416. Output::SkipToColumn(78);
  3417. Output::Print(L"#");
  3418. if (this->m_number != Js::Constants::NoByteCodeOffset)
  3419. {
  3420. Output::Print(L"%04x", this->m_number);
  3421. Output::Print(this->IsCloned()? L"*" : L" ");
  3422. }
  3423. }
  3424. if (!this->m_func->IsTopFunc())
  3425. {
  3426. Output::SkipToColumn(78);
  3427. wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  3428. Output::Print(L" Func #%s", this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
  3429. }
  3430. #ifdef BAILOUT_INJECTION
  3431. if (this->bailOutByteCodeLocation != (uint)-1)
  3432. {
  3433. Output::SkipToColumn(85);
  3434. Output::Print(L"@%4d", this->bailOutByteCodeLocation);
  3435. }
  3436. #endif
  3437. if (this->m_opcode == Js::OpCode::InlineeStart)
  3438. {
  3439. Output::Print(L" %s", this->m_func->GetJnFunction()->GetDisplayName());
  3440. }
  3441. }
  3442. void
  3443. Instr::DumpGlobOptInstrString()
  3444. {
  3445. if(this->globOptInstrString)
  3446. {
  3447. Output::Print(L"\n\n GLOBOPT INSTR: %s\n\n", this->globOptInstrString);
  3448. }
  3449. }
  3450. ///----------------------------------------------------------------------------
  3451. ///
  3452. /// Instr::Dump
  3453. ///
  3454. /// Dump this instr.
  3455. ///
  3456. ///----------------------------------------------------------------------------
  3457. void
  3458. Instr::Dump(IRDumpFlags flags)
  3459. {
  3460. bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
  3461. bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
  3462. bool const SkipByteCodeOffset = !!(flags & IRDumpFlags_SkipByteCodeOffset);
  3463. const auto PrintOpCodeName = [&]() {
  3464. Output::SkipToColumn(23);
  3465. Output::Print(L"%s ", Js::OpCodeUtil::GetOpCodeName(m_opcode));
  3466. Output::SkipToColumn(38);
  3467. };
  3468. if(m_opcode == Js::OpCode::BoundCheck || m_opcode == Js::OpCode::UnsignedBoundCheck)
  3469. {
  3470. PrintOpCodeName();
  3471. // src1 <= src2 + dst
  3472. Assert(GetSrc1());
  3473. if(GetSrc1()->IsIntConstOpnd())
  3474. {
  3475. Output::Print(L"%d", GetSrc1()->AsIntConstOpnd()->GetValue());
  3476. }
  3477. else
  3478. {
  3479. GetSrc1()->Dump(flags, m_func);
  3480. }
  3481. bool useLessThanOrEqual = true;
  3482. bool usePlus = true;
  3483. bool dumpSrc2 = false;
  3484. int32 offset = GetDst() ? GetDst()->AsIntConstOpnd()->AsInt32() : 0;
  3485. if(GetSrc2())
  3486. {
  3487. if(GetSrc2()->IsIntConstOpnd())
  3488. {
  3489. #if DBG
  3490. int32 temp;
  3491. Assert(!Int32Math::Add(offset, GetSrc2()->AsIntConstOpnd()->AsInt32(), &temp));
  3492. #endif
  3493. offset += GetSrc2()->AsIntConstOpnd()->AsInt32();
  3494. }
  3495. else
  3496. {
  3497. dumpSrc2 = true;
  3498. if(offset == -1)
  3499. {
  3500. useLessThanOrEqual = false; // < instead of <=
  3501. offset = 0;
  3502. }
  3503. else if(offset < 0 && offset != IntConstMin)
  3504. {
  3505. usePlus = false;
  3506. offset = -offset;
  3507. }
  3508. }
  3509. }
  3510. Output::Print(L" %S ", useLessThanOrEqual ? "<=" : "<");
  3511. if(dumpSrc2)
  3512. {
  3513. GetSrc2()->Dump(flags, m_func);
  3514. }
  3515. if(offset != 0)
  3516. {
  3517. if(dumpSrc2)
  3518. {
  3519. Output::Print(L" %C ", usePlus ? '+' : '-');
  3520. }
  3521. Output::Print(L"%d", offset);
  3522. }
  3523. goto PrintByteCodeOffsetEtc;
  3524. }
  3525. Output::SkipToColumn(4);
  3526. Opnd * dst = this->GetDst();
  3527. if (dst)
  3528. {
  3529. dst->Dump(flags, this->m_func);
  3530. bool const dumpMarkTemp = PHASE_DUMP(Js::MarkTempPhase, m_func->GetJnFunction())
  3531. || PHASE_TRACE(Js::MarkTempPhase, m_func->GetJnFunction());
  3532. bool const dumpMarkTempNumber = dumpMarkTemp || PHASE_DUMP(Js::MarkTempNumberPhase, m_func->GetJnFunction())
  3533. || PHASE_TRACE(Js::MarkTempNumberPhase, m_func->GetJnFunction());
  3534. bool const dumpMarkTempObject = dumpMarkTemp || PHASE_DUMP(Js::MarkTempObjectPhase, m_func->GetJnFunction())
  3535. || PHASE_TRACE(Js::MarkTempObjectPhase, m_func->GetJnFunction());
  3536. if ((dumpMarkTempNumber && (this->dstIsTempNumberTransferred || this->dstIsTempNumber))
  3537. || (dumpMarkTempObject && this->dstIsTempObject))
  3538. {
  3539. Output::Print(L"[");
  3540. if (dumpMarkTempNumber)
  3541. {
  3542. if (Js::Configuration::Global.flags.Verbose || OpCodeAttr::TempNumberProducing(this->m_opcode))
  3543. {
  3544. if (this->dstIsTempNumberTransferred)
  3545. {
  3546. Assert(this->dstIsTempNumber);
  3547. Output::Print(L"x");
  3548. }
  3549. else if (this->dstIsTempNumber)
  3550. {
  3551. Output::Print(L"#");
  3552. }
  3553. }
  3554. }
  3555. if (dumpMarkTempObject)
  3556. {
  3557. if (Js::Configuration::Global.flags.Verbose || OpCodeAttr::TempObjectProducing(this->m_opcode))
  3558. {
  3559. if (this->dstIsTempObject)
  3560. {
  3561. Output::Print(L"o");
  3562. }
  3563. }
  3564. }
  3565. Output::Print(L"tmp]");
  3566. }
  3567. if(PHASE_DUMP(Js::TrackNegativeZeroPhase, m_func->GetTopFunc()) && !ShouldCheckForNegativeZero())
  3568. {
  3569. Output::Print(L"[-0]");
  3570. }
  3571. if (PHASE_DUMP(Js::TypedArrayVirtualPhase, m_func->GetTopFunc()) && (!IsDstNotAlwaysConvertedToInt32() || !IsDstNotAlwaysConvertedToNumber()))
  3572. {
  3573. if (!IsDstNotAlwaysConvertedToInt32())
  3574. Output::Print(L"[->i]");
  3575. else
  3576. Output::Print(L"[->n]");
  3577. }
  3578. if(PHASE_DUMP(Js::TrackIntOverflowPhase, m_func->GetTopFunc()))
  3579. {
  3580. // ignoring 32-bit overflow ?
  3581. if(!ShouldCheckFor32BitOverflow())
  3582. {
  3583. // ignoring 32-bits or more ?
  3584. if(ShouldCheckForNon32BitOverflow())
  3585. Output::Print(L"[OF %d]", ignoreOverflowBitCount);
  3586. else
  3587. Output::Print(L"[OF]");
  3588. }
  3589. }
  3590. Output::SkipToColumn(20);
  3591. Output::Print(L"=");
  3592. }
  3593. PrintOpCodeName();
  3594. if (this->IsBranchInstr())
  3595. {
  3596. BranchInstr * branchInstr = this->AsBranchInstr();
  3597. LabelInstr * targetInstr = branchInstr->GetTarget();
  3598. if (targetInstr == NULL)
  3599. {
  3600. // Checking the 'm_isMultiBranch' field here directly as well to bypass asserting when tracing IR builder
  3601. if(branchInstr->m_isMultiBranch && branchInstr->IsMultiBranch())
  3602. {
  3603. IR::MultiBranchInstr * multiBranchInstr = branchInstr->AsMultiBrInstr();
  3604. multiBranchInstr->MapMultiBrLabels([](IR::LabelInstr * labelInstr) -> void
  3605. {
  3606. Output::Print(L"$L%d ", labelInstr->m_id);
  3607. });
  3608. }
  3609. else
  3610. {
  3611. Output::Print(L"??");
  3612. }
  3613. }
  3614. else
  3615. {
  3616. Output::Print(L"$L%d", targetInstr->m_id);
  3617. }
  3618. if (this->GetSrc1())
  3619. {
  3620. Output::Print(L", ");
  3621. }
  3622. }
  3623. else if (this->IsPragmaInstr() && this->m_opcode == Js::OpCode::StatementBoundary)
  3624. {
  3625. Output::Print(L"#%d", this->AsPragmaInstr()->m_statementIndex);
  3626. }
  3627. Opnd * src1 = this->GetSrc1();
  3628. if (this->m_opcode == Js::OpCode::NewScFunc || this->m_opcode == Js::OpCode::NewScGenFunc)
  3629. {
  3630. Assert(src1->IsIntConstOpnd());
  3631. Js::ParseableFunctionInfo *function = this->m_func->GetJnFunction()->GetNestedFunctionForExecution((uint)src1->AsIntConstOpnd()->GetValue())->GetParseableFunctionInfo();
  3632. Output::Print(L"func:%s()", function ? function->GetDisplayName() : L"???");
  3633. Output::Print(L", env:");
  3634. this->GetSrc2()->AsRegOpnd()->m_sym->Dump(flags);
  3635. }
  3636. else if (src1)
  3637. {
  3638. src1->Dump(flags, this->m_func);
  3639. Opnd * src2 = this->GetSrc2();
  3640. if (src2)
  3641. {
  3642. Output::Print(L", ");
  3643. src2->Dump(flags, this->m_func);
  3644. }
  3645. }
  3646. if (this->IsByteCodeUsesInstr())
  3647. {
  3648. if (this->AsByteCodeUsesInstr()->byteCodeUpwardExposedUsed)
  3649. {
  3650. bool first = true;
  3651. FOREACH_BITSET_IN_SPARSEBV(id, this->AsByteCodeUsesInstr()->byteCodeUpwardExposedUsed)
  3652. {
  3653. Output::Print(first? L"s%d" : L", s%d", id);
  3654. first = false;
  3655. }
  3656. NEXT_BITSET_IN_SPARSEBV;
  3657. }
  3658. if (this->AsByteCodeUsesInstr()->propertySymUse)
  3659. {
  3660. Output::Print(L" PropSym: %d", this->AsByteCodeUsesInstr()->propertySymUse->m_id);
  3661. }
  3662. }
  3663. PrintByteCodeOffsetEtc:
  3664. if (!AsmDumpMode && !SkipByteCodeOffset)
  3665. {
  3666. this->DumpByteCodeOffset();
  3667. }
  3668. if (!SimpleForm)
  3669. {
  3670. if (this->HasBailOutInfo() || this->HasAuxBailOut())
  3671. {
  3672. BailOutInfo * bailOutInfo = this->GetBailOutInfo();
  3673. Output::SkipToColumn(85);
  3674. if (!AsmDumpMode)
  3675. {
  3676. Output::Print(L"Bailout: #%04x", bailOutInfo->bailOutOffset);
  3677. }
  3678. if (!bailOutInfo->bailOutFunc->IsTopFunc())
  3679. {
  3680. wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  3681. Output::Print(L" Func %s", bailOutInfo->bailOutFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
  3682. }
  3683. Output::Print(L" (%S)", this->GetBailOutKindName());
  3684. }
  3685. }
  3686. if ((flags & IRDumpFlags_SkipEndLine) == 0)
  3687. {
  3688. Output::Print(L"\n");
  3689. }
  3690. }
  3691. ///----------------------------------------------------------------------------
  3692. ///
  3693. /// LabelInstr::Dump
  3694. ///
  3695. /// Dump this label.
  3696. ///
  3697. ///----------------------------------------------------------------------------
  3698. void
  3699. LabelInstr::Dump(IRDumpFlags flags)
  3700. {
  3701. if (this->m_block != NULL)
  3702. {
  3703. this->m_block->DumpHeader();
  3704. }
  3705. Output::Print(L"$L%d:", this->m_id);
  3706. if (this->isOpHelper)
  3707. {
  3708. Output::Print(L" [helper]");
  3709. }
  3710. if (this->m_isLoopTop)
  3711. {
  3712. Output::Print(L" >>>>>>>>>>>>> LOOP TOP >>>>>>>>>>>>>");
  3713. }
  3714. if (this->IsProfiledLabelInstr())
  3715. {
  3716. Output::SkipToColumn(50);
  3717. switch (this->AsProfiledLabelInstr()->loopImplicitCallFlags)
  3718. {
  3719. case Js::ImplicitCall_HasNoInfo:
  3720. Output::Print(L"Implicit call: ???");
  3721. break;
  3722. case Js::ImplicitCall_None:
  3723. Output::Print(L"Implicit call: no");
  3724. break;
  3725. default:
  3726. Output::Print(L"Implicit call: yes");
  3727. break;
  3728. }
  3729. }
  3730. if ((flags & (IRDumpFlags_AsmDumpMode | IRDumpFlags_SkipByteCodeOffset)) == 0)
  3731. {
  3732. this->DumpByteCodeOffset();
  3733. }
  3734. Output::Print(L"\n");
  3735. }
  3736. void
  3737. PragmaInstr::Dump(IRDumpFlags flags)
  3738. {
  3739. if (Js::Configuration::Global.flags.PrintSrcInDump && this->m_opcode == Js::OpCode::StatementBoundary)
  3740. {
  3741. this->m_func->GetJnFunction()->PrintStatementSourceLine(this->m_statementIndex);
  3742. }
  3743. __super::Dump(flags);
  3744. }
  3745. ///----------------------------------------------------------------------------
  3746. ///
  3747. /// Instr::Dump
  3748. ///
  3749. /// Dump a window of instructions around this instr.
  3750. ///
  3751. ///----------------------------------------------------------------------------
  3752. void
  3753. Instr::Dump(int window)
  3754. {
  3755. Instr * instr;
  3756. int i;
  3757. Output::Print(L"-------------------------------------------------------------------------------");
  3758. if (this == NULL)
  3759. {
  3760. return;
  3761. }
  3762. for (i = 0, instr = this; (instr->m_prev != NULL && i < window/2); instr = instr->m_prev, ++i)
  3763. {} // Nothing
  3764. for (i = 0; (instr != nullptr && i < window); instr = instr->m_next, ++i)
  3765. {
  3766. if (instr == this)
  3767. {
  3768. Output::Print(L"=>");
  3769. }
  3770. instr->Dump();
  3771. }
  3772. }
  3773. void
  3774. Instr::Dump()
  3775. {
  3776. this->Dump(IRDumpFlags_None);
  3777. }
  3778. void
  3779. Instr::DumpSimple()
  3780. {
  3781. this->Dump(IRDumpFlags_SimpleForm);
  3782. }
  3783. wchar_t *
  3784. Instr::DumpString()
  3785. {
  3786. Output::CaptureStart();
  3787. this->Dump();
  3788. return Output::CaptureEnd();
  3789. }
  3790. void
  3791. Instr::DumpRange(Instr *instrEnd)
  3792. {
  3793. Output::Print(L"-------------------------------------------------------------------------------\n");
  3794. FOREACH_INSTR_IN_RANGE(instr, this, instrEnd)
  3795. {
  3796. instr->Dump();
  3797. }
  3798. NEXT_INSTR_IN_RANGE;
  3799. Output::Print(L"-------------------------------------------------------------------------------\n");
  3800. }
  3801. #endif
  3802. } // namespace IR