/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 5 ĠJetBrains Ġs . r . o . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . codegen . inline Ċ Ċ import Ġcom . google . common . collect . LinkedList Multimap Ċ import Ġorg . jetbrains . kotlin . codegen . optimization . common . is Mean ing ful Ċ import Ġorg . jetbrains . org . object web . asm . tree .* Ċ import Ġjava . util .* Ċ Ċ abstract Ġclass ĠCover ing Try Catch Node Processor ( parameter Size : ĠInt ) Ġ{ ĊĠĠĠ Ġval Ġtry Blocks Meta Info : ĠInterval Meta Info < Try Catch Block NodeInfo > Ġ= ĠInterval Meta Info ( this ) ĊĠĠĠ Ġval ĠlocalVar s Meta Info : ĠInterval Meta Info < Local Var Node Wrapper > Ġ= ĠInterval Meta Info ( this ) ĊĊĠĠĠ Ġvar Ġnext Free Local Index : ĠInt Ġ= Ġparameter Size ĊĠĠĠĠĠĠĠ Ġprivate Ġset ĊĊĠĠĠ Ġfun Ġget Start Nodes ( label : ĠLabel Node ): ĠList < Try Catch Block NodeInfo > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Blocks Meta Info . interval Starts . get ( label ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget End Nodes ( label : ĠLabel Node ): ĠList < Try Catch Block NodeInfo > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Blocks Meta Info . interval End s . get ( label ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġopen Ġfun Ġprocess Instruction ( cur Instr : ĠAbstract Insn Node , Ġdirect Order : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( cur Instr Ġis ĠVar Insn Node Ġ|| Ġcur Instr Ġis ĠI inc Insn Node ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġarg Size Ġ= Ġget Load Store Arg Size ( cur Instr . opcode ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvar Index Ġ= Ġif Ġ( cur Instr Ġis ĠVar Insn Node ) Ġcur Instr .` var ` Ġelse Ġ( cur Instr Ġas ĠI inc Insn Node ). ` var ` ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnext Free Local Index Ġ= ĠMath . max ( next Free Local Index , Ġvar Index Ġ+ Ġarg Size ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( cur Instr Ġis ĠLabel Node ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Blocks Meta Info . process Current ( cur Instr , Ġdirect Order ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠlocalVar s Meta Info . process Current ( cur Instr , Ġdirect Order ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġabstract Ġfun Ġinstruction Index ( inst : ĠAbstract Insn Node ): ĠInt ĊĊĠĠĠ Ġfun Ġsort Try Catch Blocks ( intervals : ĠList < Try Catch Block NodeInfo >): ĠList < Try Catch Block NodeInfo > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcomp Ġ= ĠComparator Ġ{ Ġt 1 : ĠTry Catch Block NodeInfo , Ġt 2 : ĠTry Catch Block NodeInfo Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġresult Ġ= Ġinstruction Index ( t 1 . handler ) Ġ- Ġinstruction Index ( t 2 . handler ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Ġ= Ġinstruction Index ( t 1 . start Label ) Ġ- Ġinstruction Index ( t 2 . start Label ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( false ) Ġ{ Ġ" Error : Ġsupport Ġmult ic atch Ġfinal lies : Ġ${ t 1 . handler }, Ġ${ t 2 . handler }" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Ġ= Ġinstruction Index ( t 1 . end Label ) Ġ- Ġinstruction Index ( t 2 . end Label ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠCollections . sort ( intervals , Ġcomp ) ĊĠĠĠĠĠĠĠ Ġreturn Ġintervals ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsubstitute Try Block Nodes ( node : ĠMethod Node ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnode . try Catch Blocks . clear () ĊĠĠĠĠĠĠĠ Ġsort Try Catch Blocks ( try Blocks Meta Info . all Intervals ) ĊĠĠĠĠĠĠĠ Ġfor Ġ( info Ġin Ġtry Blocks Meta Info . get Mean ing ful Intervals ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnode . try Catch Blocks . add ( info . node ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsubstitute Local Var Table ( node : ĠMethod Node ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnode . local Variables . clear () ĊĠĠĠĠĠĠĠ Ġfor Ġ( info Ġin ĠlocalVar s Meta Info . get Mean ing ful Intervals ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnode . local Variables . add ( info . node ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ class ĠInterval Meta Info < T Ġ: ĠSplit table Interval < T >>( private Ġval Ġprocessor : ĠCover ing Try Catch Node Processor ) Ġ{ ĊĠĠĠ Ġval Ġinterval Starts Ġ= ĠLinkedList Multimap . create < Label Node , ĠT >() ĊĠĠĠ Ġval Ġinterval End s Ġ= ĠLinkedList Multimap . create < Label Node , ĠT >() ĊĠĠĠ Ġval Ġall Intervals : ĠArrayList < T > Ġ= Ġarray ListOf () ĊĠĠĠ Ġval Ġcurrent Intervals : ĠMutable Set < T > Ġ= Ġlinked Set Of () ĊĊĠĠĠ Ġfun Ġadd New Interval ( new Info : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnew Info . verify ( processor ) ĊĠĠĠĠĠĠĠ Ġinterval Starts . put ( new Info . start Label , Ġnew Info ) ĊĠĠĠĠĠĠĠ Ġinterval End s . put ( new Info . end Label , Ġnew Info ) ĊĠĠĠĠĠĠĠ Ġall Intervals . add ( new Info ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġremap Start Label ( old Start : ĠLabel Node , Ġrem apped : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġrem apped . verify ( processor ) ĊĠĠĠĠĠĠĠ Ġinterval Starts . remove ( old Start , Ġrem apped ) ĊĠĠĠĠĠĠĠ Ġinterval Starts . put ( rem apped . start Label , Ġrem apped ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġremap End Label ( old End : ĠLabel Node , Ġrem apped : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġrem apped . verify ( processor ) ĊĠĠĠĠĠĠĠ Ġinterval End s . remove ( old End , Ġrem apped ) ĊĠĠĠĠĠĠĠ Ġinterval End s . put ( rem apped . end Label , Ġrem apped ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsplit Current Intervals ( by : ĠInterval , Ġkeep Start : ĠBoolean ): ĠList < Split Pair < T >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġcurrent Intervals . map Ġ{ Ġsplit ( it , Ġby , Ġkeep Start ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsplit And Remove Current Intervals ( by : ĠInterval , Ġkeep Start : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcurrent Intervals . map Ġ{ Ġsplit And Remove Interval ( it , Ġby , Ġkeep Start ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġprocess Current ( cur Ins : ĠLabel Node , Ġdirect Order : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġget Interval ( cur Ins , Ġdirect Order ). forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġadded Ġ= Ġcurrent Intervals . add ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( added ) Ġ{ Ġ" Wrong Ġinterval Ġstructure : Ġ$ cur Ins , Ġ$ it " Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġget Interval ( cur Ins , Ġ! direct Order ). forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġremoved Ġ= Ġcurrent Intervals . remove ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( removed ) Ġ{ Ġ" Wrong Ġinterval Ġstructure : Ġ$ cur Ins , Ġ$ it " Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsplit ( interval : ĠT , Ġby : ĠInterval , Ġkeep Start : ĠBoolean ): ĠSplit Pair < T > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsplit Ġ= Ġinterval . split ( by , Ġkeep Start ) ĊĠĠĠĠĠĠĠ Ġif Ġ(! keep Start ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremap Start Label ( split . new Part . start Label , Ġsplit . patched Part ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremap End Label ( split . new Part . end Label , Ġsplit . patched Part ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġadd New Interval ( split . new Part ) ĊĠĠĠĠĠĠĠ Ġreturn Ġsplit ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsplit And Remove Interval ( interval : ĠT , Ġby : ĠInterval , Ġkeep Start : ĠBoolean ): ĠSplit Pair < T > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsplit Pair Ġ= Ġsplit ( interval , Ġby , Ġkeep Start ) ĊĠĠĠĠĠĠĠ Ġval Ġremoved Ġ= Ġcurrent Intervals . remove ( split Pair . patched Part ) ĊĠĠĠĠĠĠĠ Ġassert ( removed ) Ġ{ Ġ" Wrong Ġinterval Ġstructure : Ġ$ split Pair " Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġsplit Pair ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Interval ( cur Ins : ĠLabel Node , ĠisOpen : ĠBoolean ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( isOpen ) Ġinterval Starts . get ( cur Ins ) Ġelse Ġinterval End s . get ( cur Ins ) Ċ } Ċ Ċ fun ĠTry Catch Block Node . is Mean ing less () Ġ= ĠSimple Interval ( start , Ġend ). is Mean ing less () Ċ Ċ fun ĠInterval . is Mean ing less (): ĠBoolean Ġ{ ĊĠĠĠ Ġval Ġstart Ġ= Ġthis . start Label ĊĠĠĠ Ġvar Ġend : ĠAbstract Insn Node Ġ= Ġthis . end Label ĊĠĠĠ Ġwhile Ġ( end Ġ!= Ġstart Ġ&& Ġ! end . is Mean ing ful ) Ġ{ ĊĠĠĠĠĠĠĠ Ġend Ġ= Ġend . previous ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġstart Ġ== Ġend Ċ } Ċ Ċ fun Ġ< T Ġ: ĠSplit table Interval < T >> ĠInterval Meta Info < T >. get Mean ing ful Intervals (): ĠList < T > Ġ{ ĊĠĠĠ Ġreturn Ġall Intervals . filter Not Ġ{ Ġit . is Mean ing less () Ġ} Ċ } Ċ Ċ class ĠDefault Processor ( val Ġnode : ĠMethod Node , Ġparameter Size : ĠInt ) Ġ: ĠCover ing Try Catch Node Processor ( parameter Size ) Ġ{ ĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġnode . try Catch Blocks . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Blocks Meta Info . add New Interval ( Try Catch Block NodeInfo ( it , Ġfalse )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġnode . local Variables . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠlocalVar s Meta Info . add New Interval ( Local Var Node Wrapper ( it )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġinstruction Index ( inst : ĠAbstract Insn Node ): ĠInt Ġ= Ġnode . instructions . indexOf ( inst ) Ċ } Ċ Ċ class ĠLocal Var Node Wrapper ( val Ġnode : ĠLocal Variable Node ) Ġ: ĠInterval , ĠSplit table Interval < Local Var Node Wrapper > Ġ{ ĊĠĠĠ Ġoverride Ġval Ġstart Label : ĠLabel Node ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġnode . start ĊĠĠĠ Ġoverride Ġval Ġend Label : ĠLabel Node ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġnode . end ĊĊĠĠĠ Ġoverride Ġfun Ġsplit ( split By : ĠInterval , Ġkeep Start : ĠBoolean ): ĠSplit Pair < Local Var Node Wrapper > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnew Part Interval Ġ= Ġif Ġ( keep Start ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġold End Ġ= Ġend Label ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnode . end Ġ= Ġsplit By . start Label ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( split By . end Label , Ġold End ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġold Start Ġ= Ġstart Label ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnode . start Ġ= Ġsplit By . end Label ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( old Start , Ġsplit By . start Label ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠSplit Pair ( this , ĠLocal Var Node Wrapper ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLocal Variable Node ( node . name , Ġnode . desc , Ġnode . signature , Ġnew Part Interval . first , Ġnew Part Interval . second , Ġnode . index ) ĊĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠ Ġ} Ċ } Ċ