@@ -126,14 +126,22 @@ trait LiveVariables {
126
126
127
127
/** Tests if `state1` is a predecessor of `state2`.
128
128
*/
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
+ }
137
145
138
146
val finalState = asyncStates.find(as => ! asyncStates.exists(other => isPred(as.state, other.state))).get
139
147
@@ -162,12 +170,10 @@ trait LiveVariables {
162
170
LVexit = LVexit + (finalState.state -> noNull)
163
171
164
172
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
167
173
var captured : Set [Symbol ] = Set ()
168
174
169
- while (hasChanged ) {
170
- hasChanged = false
175
+ while (! currStates.isEmpty ) {
176
+ var entryChanged : List [ AsyncState ] = Nil
171
177
172
178
for (cs <- currStates) {
173
179
val LVentryOld = LVentry (cs.state)
@@ -176,44 +182,53 @@ trait LiveVariables {
176
182
val LVentryNew = LVexit (cs.state) ++ referenced.used
177
183
if (! LVentryNew .sameElements(LVentryOld )) {
178
184
LVentry = LVentry + (cs.state -> LVentryNew )
179
- hasChanged = true
185
+ entryChanged ::= cs
180
186
}
181
187
}
182
188
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
184
191
185
192
for (p <- pred) {
186
193
val LVexitOld = LVexit (p.state)
187
194
val LVexitNew = p.nextStates.flatMap(succ => LVentry (succ)).toSet
188
195
if (! LVexitNew .sameElements(LVexitOld )) {
189
196
LVexit = LVexit + (p.state -> LVexitNew )
190
- hasChanged = true
197
+ exitChanged ::= p
191
198
}
192
199
}
193
200
194
- currStates = pred
201
+ currStates = exitChanged
195
202
}
196
203
197
204
for (as <- asyncStates) {
198
205
AsyncUtils .vprintln(s " LVentry at state # ${as.state}: ${LVentry (as.state).mkString(" , " )}" )
199
206
AsyncUtils .vprintln(s " LVexit at state # ${as.state}: ${LVexit (as.state).mkString(" , " )}" )
200
207
}
201
208
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
+ }
213
225
}
214
226
227
+ lastUsagesOf0(field, at)
228
+ }
229
+
215
230
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
217
232
218
233
for ((fld, lastStates) <- lastUsages)
219
234
AsyncUtils .vprintln(s " field ${fld.symbol.name} is last used in states ${lastStates.mkString(" , " )}" )
0 commit comments