@@ -20,13 +20,16 @@ import collection.mutable
20
20
import reporting .{Profile , NoProfile }
21
21
import dotty .tools .tasty .TastyFormat .ASTsSection
22
22
23
+ object TreePickler :
24
+ class StackSizeExceeded (val mdef : tpd.MemberDef ) extends Exception
23
25
24
26
class TreePickler (pickler : TastyPickler ) {
25
27
val buf : TreeBuffer = new TreeBuffer
26
28
pickler.newSection(ASTsSection , buf)
27
29
import buf ._
28
30
import pickler .nameBuffer .nameIndex
29
31
import tpd ._
32
+ import TreePickler .*
30
33
31
34
private val symRefs = Symbols .MutableSymbolMap [Addr ](256 )
32
35
private val forwardSymRefs = Symbols .MutableSymbolMap [List [Addr ]]()
@@ -53,7 +56,7 @@ class TreePickler(pickler: TastyPickler) {
53
56
def docString (tree : untpd.MemberDef ): Option [Comment ] =
54
57
Option (docStrings.lookup(tree))
55
58
56
- private def withLength (op : => Unit ) = {
59
+ private inline def withLength (inline op : Unit ) = {
57
60
val lengthAddr = reserveRef(relative = true )
58
61
op
59
62
fillRef(lengthAddr, currentAddr, relative = true )
@@ -328,16 +331,24 @@ class TreePickler(pickler: TastyPickler) {
328
331
registerDef(sym)
329
332
writeByte(tag)
330
333
val addr = currentAddr
331
- withLength {
332
- pickleName(sym.name)
333
- pickleParams
334
- tpt match {
335
- case _ : Template | _ : Hole => pickleTree(tpt)
336
- case _ if tpt.isType => pickleTpt(tpt)
334
+ try
335
+ withLength {
336
+ pickleName(sym.name)
337
+ pickleParams
338
+ tpt match {
339
+ case _ : Template | _ : Hole => pickleTree(tpt)
340
+ case _ if tpt.isType => pickleTpt(tpt)
341
+ }
342
+ pickleTreeUnlessEmpty(rhs)
343
+ pickleModifiers(sym, mdef)
337
344
}
338
- pickleTreeUnlessEmpty(rhs)
339
- pickleModifiers(sym, mdef)
340
- }
345
+ catch
346
+ case ex : Throwable =>
347
+ if ! ctx.settings.YnoDecodeStacktraces .value
348
+ && handleRecursive.underlyingStackOverflowOrNull(ex) != null then
349
+ throw StackSizeExceeded (mdef)
350
+ else
351
+ throw ex
341
352
if sym.is(Method ) && sym.owner.isClass then
342
353
profile.recordMethodSize(sym, currentAddr.index - addr.index, mdef.span)
343
354
for
@@ -784,7 +795,17 @@ class TreePickler(pickler: TastyPickler) {
784
795
785
796
def pickle (trees : List [Tree ])(using Context ): Unit = {
786
797
profile = Profile .current
787
- trees.foreach(tree => if (! tree.isEmpty) pickleTree(tree))
798
+ for tree <- trees do
799
+ try
800
+ if ! tree.isEmpty then pickleTree(tree)
801
+ catch case ex : StackSizeExceeded =>
802
+ report.error(
803
+ em """ Recursion limit exceeded while pickling ${ex.mdef}
804
+ |in ${ex.mdef.symbol.showLocated}.
805
+ |You could try to increase the stacksize using the -Xss JVM option.
806
+ |For the unprocessed stack trace, compile with -Yno-decode-stacktraces. """ ,
807
+ ex.mdef.srcPos)
808
+
788
809
def missing = forwardSymRefs.keysIterator
789
810
.map(sym => i " ${sym.showLocated} (line ${sym.srcPos.line}) # ${sym.id}" )
790
811
.toList
0 commit comments