@@ -1144,35 +1144,38 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
1144
1144
expand(tree, tree.tpe.widen)
1145
1145
}
1146
1146
1147
- inline val MapRecursionLimit = 10
1148
-
1149
1147
extension (trees : List [Tree ])
1150
1148
1151
- /** A map that expands to a recursive function. It's equivalent to
1149
+ /** Equivalent (but faster) to
1152
1150
*
1153
1151
* flatten(trees.mapConserve(op))
1154
1152
*
1155
- * and falls back to it after `MaxRecursionLimit` recursions.
1156
- * Before that it uses a simpler method that uses stackspace
1157
- * instead of heap.
1158
- * Note `op` is duplicated in the generated code, so it should be
1159
- * kept small.
1153
+ * assuming that `trees` does not contain `Thicket`s to start with.
1160
1154
*/
1161
- inline def mapInline (inline op : Tree => Tree ): List [Tree ] =
1162
- def recur (trees : List [Tree ], count : Int ): List [Tree ] =
1163
- if count > MapRecursionLimit then
1164
- // use a slower implementation that avoids stack overflows
1165
- flatten(trees.mapConserve(op))
1166
- else trees match
1167
- case tree :: rest =>
1168
- val tree1 = op(tree)
1169
- val rest1 = recur(rest, count + 1 )
1170
- if (tree1 eq tree) && (rest1 eq rest) then trees
1171
- else tree1 match
1172
- case Thicket (elems1) => elems1 ::: rest1
1173
- case _ => tree1 :: rest1
1174
- case nil => nil
1175
- recur(trees, 0 )
1155
+ inline def flattenedMapConserve (inline f : Tree => Tree ): List [Tree ] =
1156
+ @ tailrec
1157
+ def loop (mapped : ListBuffer [Tree ] | Null , unchanged : List [Tree ], pending : List [Tree ]): List [Tree ] =
1158
+ if pending.isEmpty then
1159
+ if mapped == null then unchanged
1160
+ else mapped.prependToList(unchanged)
1161
+ else
1162
+ val head0 = pending.head
1163
+ val head1 = f(head0)
1164
+
1165
+ if head1 eq head0 then
1166
+ loop(mapped, unchanged, pending.tail)
1167
+ else
1168
+ val buf = if mapped == null then new ListBuffer [Tree ] else mapped
1169
+ var xc = unchanged
1170
+ while xc ne pending do
1171
+ buf += xc.head
1172
+ xc = xc.tail
1173
+ head1 match
1174
+ case Thicket (elems1) => buf ++= elems1
1175
+ case _ => buf += head1
1176
+ val tail0 = pending.tail
1177
+ loop(buf, tail0, tail0)
1178
+ loop(null , trees, trees)
1176
1179
1177
1180
/** Transform statements while maintaining import contexts and expression contexts
1178
1181
* in the same way as Typer does. The code addresses additional concerns:
0 commit comments