1
1
package scala .async .internal
2
2
3
+ import scala .collection .immutable .IntMap
4
+
3
5
trait LiveVariables {
4
6
self : AsyncMacro =>
5
7
import c .universe ._
@@ -48,7 +50,7 @@ trait LiveVariables {
48
50
*/
49
51
def liveVars (asyncStates : List [AsyncState ], liftables : List [Tree ]): Map [Tree , Set [Int ]] = {
50
52
val liftedSyms : Set [Symbol ] = // include only vars
51
- liftables.filter {
53
+ liftables.iterator. filter {
52
54
case ValDef (mods, _, _, _) => mods.hasFlag(MUTABLE )
53
55
case _ => false
54
56
}.map(_.symbol).toSet
@@ -122,20 +124,30 @@ trait LiveVariables {
122
124
* A state `i` is contained in the list that is the value to which
123
125
* key `j` maps iff control can flow from state `j` to state `i`.
124
126
*/
125
- val cfg : Map [Int , List [Int ]] = asyncStates.map(as => as.state -> as.nextStates).toMap
127
+ val cfg : Map [Int , Array [Int ]] = {
128
+ var res = IntMap .empty[Array [Int ]]
129
+
130
+ for (as <- asyncStates) res = res.updated(as.state, as.nextStates)
131
+ res
132
+ }
126
133
127
134
/** Tests if `state1` is a predecessor of `state2`.
128
135
*/
129
136
def isPred (state1 : Int , state2 : Int ): Boolean = {
130
- val seen = scala.collection.mutable. HashSet [ Int ] ()
137
+ val seen = new StateSet ()
131
138
132
139
def isPred0 (state1 : Int , state2 : Int ): Boolean =
133
140
if (state1 == state2) false
134
- else if (seen(state1)) false // breaks cycles in the CFG
141
+ else if (seen.contains (state1)) false // breaks cycles in the CFG
135
142
else cfg get state1 match {
136
143
case Some (nextStates) =>
137
144
seen += state1
138
- nextStates.contains(state2) || nextStates.exists(isPred0(_, state2))
145
+ var i = 0
146
+ while (i < nextStates.length) {
147
+ if (nextStates(i) == state2 || isPred0(nextStates(i), state2)) return true
148
+ i += 1
149
+ }
150
+ false
139
151
case None =>
140
152
false
141
153
}
@@ -164,8 +176,8 @@ trait LiveVariables {
164
176
* 7. repeat if something has changed
165
177
*/
166
178
167
- var LVentry = Map [ Int , Set [Symbol ]]() withDefaultValue Set [Symbol ]()
168
- var LVexit = Map [ Int , Set [Symbol ]]() withDefaultValue Set [Symbol ]()
179
+ var LVentry = IntMap [ Set [Symbol ]]() withDefaultValue Set [Symbol ]()
180
+ var LVexit = IntMap [ Set [Symbol ]]() withDefaultValue Set [Symbol ]()
169
181
170
182
// All fields are declared to be dead at the exit of the final async state, except for the ones
171
183
// that cannot be nulled out at all (those in noNull), because they have been captured by a nested def.
@@ -174,6 +186,14 @@ trait LiveVariables {
174
186
var currStates = List (finalState) // start at final state
175
187
var captured : Set [Symbol ] = Set ()
176
188
189
+ def contains (as : Array [Int ], a : Int ): Boolean = {
190
+ var i = 0
191
+ while (i < as.length) {
192
+ if (as(i) == a) return true
193
+ i += 1
194
+ }
195
+ false
196
+ }
177
197
while (! currStates.isEmpty) {
178
198
var entryChanged : List [AsyncState ] = Nil
179
199
@@ -183,19 +203,19 @@ trait LiveVariables {
183
203
captured ++= referenced.captured
184
204
val LVentryNew = LVexit (cs.state) ++ referenced.used
185
205
if (! LVentryNew .sameElements(LVentryOld )) {
186
- LVentry = LVentry + (cs.state -> LVentryNew )
206
+ LVentry = LVentry .updated (cs.state, LVentryNew )
187
207
entryChanged ::= cs
188
208
}
189
209
}
190
210
191
- val pred = entryChanged.flatMap(cs => asyncStates.filter(_.nextStates. contains(cs.state)))
211
+ val pred = entryChanged.flatMap(cs => asyncStates.filter(state => contains(state.nextStates, cs.state)))
192
212
var exitChanged : List [AsyncState ] = Nil
193
213
194
214
for (p <- pred) {
195
215
val LVexitOld = LVexit (p.state)
196
216
val LVexitNew = p.nextStates.flatMap(succ => LVentry (succ)).toSet
197
217
if (! LVexitNew .sameElements(LVexitOld )) {
198
- LVexit = LVexit + (p.state -> LVexitNew )
218
+ LVexit = LVexit .updated (p.state, LVexitNew )
199
219
exitChanged ::= p
200
220
}
201
221
}
@@ -223,7 +243,7 @@ trait LiveVariables {
223
243
Set (at.state)
224
244
case _ =>
225
245
avoid += at
226
- val preds = asyncStates.filter(_.nextStates. contains(at.state)).toSet
246
+ val preds = asyncStates.filter(state => contains(state.nextStates, at.state)).toSet
227
247
preds.flatMap(p => lastUsagesOf0(field, p))
228
248
}
229
249
}
@@ -248,7 +268,7 @@ trait LiveVariables {
248
268
val succNums = lastAsyncState.nextStates
249
269
// all successor states that are not indirect predecessors
250
270
// filter out successor states where the field is live at the entry
251
- succNums.filter(num => ! isPred(num, s)).filterNot(num => LVentry (num).contains(fld.symbol))
271
+ succNums.iterator. filter(num => ! isPred(num, s)).filterNot(num => LVentry (num).contains(fld.symbol))
252
272
}
253
273
}
254
274
(fld, killAt)
0 commit comments