@@ -126,14 +126,22 @@ trait LiveVariables {
126126
127127 /** Tests if `state1` is a predecessor of `state2`.
128128 */
129- def isPred (state1 : Int , state2 : Int , seen : Set [Int ] = Set ()): Boolean =
130- if (seen(state1)) false // breaks cycles in the CFG
131- else cfg get state1 match {
132- case Some (nextStates) =>
133- nextStates.contains(state2) || nextStates.exists(isPred(_, state2, seen + state1))
134- case None =>
135- false
136- }
129+ def isPred (state1 : Int , state2 : Int ): Boolean = {
130+ val seen = scala.collection.mutable.HashSet [Int ]()
131+
132+ def isPred0 (state1 : Int , state2 : Int ): Boolean =
133+ if (state1 == state2) false
134+ else if (seen(state1)) false // breaks cycles in the CFG
135+ else cfg get state1 match {
136+ case Some (nextStates) =>
137+ seen += state1
138+ nextStates.contains(state2) || nextStates.exists(isPred0(_, state2))
139+ case None =>
140+ false
141+ }
142+
143+ isPred0(state1, state2)
144+ }
137145
138146 val finalState = asyncStates.find(as => ! asyncStates.exists(other => isPred(as.state, other.state))).get
139147
@@ -162,12 +170,10 @@ trait LiveVariables {
162170 LVexit = LVexit + (finalState.state -> noNull)
163171
164172 var currStates = List (finalState) // start at final state
165- var pred = List [AsyncState ]() // current predecessor states
166- var hasChanged = true // if something has changed we need to continue iterating
167173 var captured : Set [Symbol ] = Set ()
168174
169- while (hasChanged ) {
170- hasChanged = false
175+ while (! currStates.isEmpty ) {
176+ var entryChanged : List [ AsyncState ] = Nil
171177
172178 for (cs <- currStates) {
173179 val LVentryOld = LVentry (cs.state)
@@ -176,44 +182,53 @@ trait LiveVariables {
176182 val LVentryNew = LVexit (cs.state) ++ referenced.used
177183 if (! LVentryNew .sameElements(LVentryOld )) {
178184 LVentry = LVentry + (cs.state -> LVentryNew )
179- hasChanged = true
185+ entryChanged ::= cs
180186 }
181187 }
182188
183- pred = currStates.flatMap(cs => asyncStates.filter(_.nextStates.contains(cs.state)))
189+ val pred = entryChanged.flatMap(cs => asyncStates.filter(_.nextStates.contains(cs.state)))
190+ var exitChanged : List [AsyncState ] = Nil
184191
185192 for (p <- pred) {
186193 val LVexitOld = LVexit (p.state)
187194 val LVexitNew = p.nextStates.flatMap(succ => LVentry (succ)).toSet
188195 if (! LVexitNew .sameElements(LVexitOld )) {
189196 LVexit = LVexit + (p.state -> LVexitNew )
190- hasChanged = true
197+ exitChanged ::= p
191198 }
192199 }
193200
194- currStates = pred
201+ currStates = exitChanged
195202 }
196203
197204 for (as <- asyncStates) {
198205 AsyncUtils .vprintln(s " LVentry at state # ${as.state}: ${LVentry (as.state).mkString(" , " )}" )
199206 AsyncUtils .vprintln(s " LVexit at state # ${as.state}: ${LVexit (as.state).mkString(" , " )}" )
200207 }
201208
202- def lastUsagesOf (field : Tree , at : AsyncState , avoid : Set [AsyncState ]): Set [Int ] =
203- if (avoid(at)) Set ()
204- else if (captured(field.symbol)) {
205- Set ()
206- }
207- else LVentry get at.state match {
208- case Some (fields) if fields.exists(_ == field.symbol) =>
209- Set (at.state)
210- case _ =>
211- val preds = asyncStates.filter(_.nextStates.contains(at.state)).toSet
212- preds.flatMap(p => lastUsagesOf(field, p, avoid + at))
209+ def lastUsagesOf (field : Tree , at : AsyncState ): Set [Int ] = {
210+ val avoid = scala.collection.mutable.HashSet [AsyncState ]()
211+
212+ def lastUsagesOf0 (field : Tree , at : AsyncState ): Set [Int ] = {
213+ if (avoid(at)) Set ()
214+ else if (captured(field.symbol)) {
215+ Set ()
216+ }
217+ else LVentry get at.state match {
218+ case Some (fields) if fields.exists(_ == field.symbol) =>
219+ Set (at.state)
220+ case _ =>
221+ avoid += at
222+ val preds = asyncStates.filter(_.nextStates.contains(at.state)).toSet
223+ preds.flatMap(p => lastUsagesOf0(field, p))
224+ }
213225 }
214226
227+ lastUsagesOf0(field, at)
228+ }
229+
215230 val lastUsages : Map [Tree , Set [Int ]] =
216- liftables.map(fld => (fld -> lastUsagesOf(fld, finalState, Set () ))).toMap
231+ liftables.map(fld => (fld -> lastUsagesOf(fld, finalState))).toMap
217232
218233 for ((fld, lastStates) <- lastUsages)
219234 AsyncUtils .vprintln(s " field ${fld.symbol.name} is last used in states ${lastStates.mkString(" , " )}" )
0 commit comments