/* Ċ Ġ* Ġ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 . optimization Ċ Ċ import Ġorg . jetbrains . kotlin . codegen . optimization . common . is Mean ing ful Ċ import Ġorg . jetbrains . kotlin . codegen . optimization . transformer . Method Transformer Ċ import Ġorg . jetbrains . org . object web . asm . Op codes Ċ import Ġorg . jetbrains . org . object web . asm . tree .* Ċ Ċ class ĠRed undant G oto Method Transformer Ġ: ĠMethod Transformer () Ġ{ ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRemoves Ġredundant ĠGOTO 's Ġin Ġthe Ġfollowing Ġcases : ĊĠĠĠĠ Ġ* Ġ Ġ( 1 ) Ġsubsequent Ġlabels ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġ... ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġgoto ĠLabel Ġ( can Ġbe Ġremoved ) ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġnop ĠĠĠĠĠĠĠ Ġ( any Ġnumber Ġof Ġthem , Ġor Ġmaybe Ġnone ; Ġwill Ġbe Ġremoved Ġby ĠRed undant N ops Cleanup Method Transformer ) ĊĠĠĠĠ Ġ* ĠĠĠĠĠ ĠLabel : ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġ... ĊĠĠĠĠ Ġ* Ġ Ġ( 2 ) Ġindirect Ġgoto ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġ... ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġ< branch Ġinstruction > ĠLabel Ġ( can Ġbe Ġre w rote Ġto Ġ< branch Ġinstruction > ĠLabel 2 ) ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġ... ĊĠĠĠĠ Ġ* ĠĠĠĠĠ ĠLabel : ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġgoto ĠLabel 2 Ġ( must Ġnot Ġbe Ġremoved Ġdue Ġto Ġthe Ġprevious Ġinstruction Ġthat Ġcan Ġfall through Ġon Ġthis Ġgoto ) ĊĠĠĠĠ Ġ* ĠĠĠĠĠ Ġ... ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġtransform ( internal ClassName : ĠString , Ġmethod Node : ĠMethod Node ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġins ns Ġ= Ġmethod Node . instructions . toArray (). apply Ġ{ Ġreverse () Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġins ns ToRemove Ġ= Ġarray ListOf < Abstract Insn Node >() ĊĠĠĠĠĠĠĠ Ġval Ġcurrent Labels Ġ= Ġhash Set Of < Label Node >() ĊĠĠĠĠĠĠĠ Ġval Ġlabels To Replace Ġ= Ġhash Map Of < Label Node , ĠJump Insn Node >() ĊĠĠĠĠĠĠĠ Ġvar Ġpending G oto : ĠJump Insn Node ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( insn Ġin Ġins ns ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġcan Ġremove Ġjumps Ġover Ġlabels , ĠN OP s , ĠG OT Os Ġwith Ġthe Ġsame Ġtarget , Ġand Ġfake ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġinstructions Ġused Ġto Ġdescribe Ġthe Ġcurrent Ġframe Ġstate . ĠWe Ġhave Ġto Ġkeep Ġjumps ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġover Ġline Ġnumbers , Ġthough , Ġas Ġotherwise Ġsomething Ġlike Ġan Ġ` if ` Ġwith Ġan Ġempty ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ` else ` Ġwill Ġtrigger Ġa Ġbreakpoint Ġinside Ġthe Ġ` else ` Ġeven Ġwhen Ġthe Ġcondition Ġis Ġtrue . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinsn Ġis ĠLabel Node Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Labels . add ( insn ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpending G oto ?. let Ġ{ Ġlabels To Replace [ insn ] Ġ= Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinsn . opcode Ġ== ĠOp codes . GOTO Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpending G oto Ġ= Ġinsn Ġas ĠJump Insn Node ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( insn . label Ġin Ġcurrent Labels ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġins ns ToRemove . add ( insn ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Labels . clear () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinsn Ġis ĠLine Number Node Ġ|| Ġ( insn . is Mean ing ful Ġ&& Ġinsn . opcode Ġ!= ĠOp codes . NOP ) Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Labels . clear () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpending G oto Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠRewrite Ġbranch Ġinstructions . ĊĠĠĠĠĠĠĠ Ġif Ġ( labels To Replace . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġins ns . filter Is Instance < Jump Insn Node >(). forEach Ġ{ Ġrewrite Label IfNeeded ( it , Ġlabels To Replace ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( insn ToRemove Ġin Ġins ns ToRemove ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Node . instructions . insertBefore ( insn ToRemove , ĠIn sn Node ( Op codes . NOP )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Node . instructions . remove ( insn ToRemove ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrewrite Label IfNeeded ( ĊĠĠĠĠĠĠĠ Ġjump Insn : ĠJump Insn Node , ĊĠĠĠĠĠĠĠ Ġlabels To Replace : ĠMap < Label Node , ĠJump Insn Node > ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlast Jump Insn Ġ= ĠgetLast Target Jump Insn ( jump Insn , Ġlabels To Replace , Ġmutable ListOf ()) ĊĠĠĠĠĠĠĠ Ġif Ġ( last Jump Insn Ġ!= Ġnull Ġ&& Ġlast Jump Insn Ġ!= Ġjump Insn ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDo Ġnot Ġremove Ġthe Ġold Ġlabel Ġbecause Ġit Ġcan Ġbe Ġused Ġto Ġdefine Ġa Ġlocal Ġvariable Ġrange . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjump Insn . label Ġ= Ġlast Jump Insn . label ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠgetLast Target Jump Insn ( ĊĠĠĠĠĠĠĠ Ġjump Insn : ĠJump Insn Node , ĊĠĠĠĠĠĠĠ Ġlabels To Replace : ĠMap < Label Node , ĠJump Insn Node >, ĊĠĠĠĠĠĠĠ Ġalready Vis ited : ĠMutable List < Jump Insn Node > ĊĠĠĠ Ġ): ĠJump Insn Node ? Ġ{ ĊĠĠĠĠĠĠĠ Ġlabels To Replace [ jump Insn . label ]?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( already Vis ited . contains ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCycle Ġdetected , Ġdo Ġno Ġapply Ġgoto Ġoptimization ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġalready Vis ited . add ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠgetLast Target Jump Insn ( it , Ġlabels To Replace , Ġalready Vis ited ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġjump Insn ĊĠĠĠ Ġ} Ċ } Ċ