@@ -10,6 +10,7 @@ import ast.Trees._
1010import ast .{untpd , tpd }
1111import Contexts ._ , Symbols ._ , Types ._ , Names ._ , Constants ._ , Decorators ._ , Annotations ._ , Flags ._
1212import Denotations .MultiDenotation
13+ import Comments .{Comment , CommentsContext }
1314import typer .Inliner
1415import NameKinds ._
1516import StdNames .nme
@@ -18,6 +19,7 @@ import printing.Printer
1819import printing .Texts ._
1920import util .SourceFile
2021import annotation .constructorOnly
22+ import collection .mutable
2123
2224object TreePickler {
2325
@@ -44,6 +46,25 @@ class TreePickler(pickler: TastyPickler) {
4446 private val forwardSymRefs = Symbols .newMutableSymbolMap[List [Addr ]]
4547 private val pickledTypes = new java.util.IdentityHashMap [Type , Any ] // Value type is really Addr, but that's not compatible with null
4648
49+ /** A list of annotation trees for every member definition, so that later
50+ * parallel position pickling does not need to access and force symbols.
51+ */
52+ private val annotTrees = util.HashTable [untpd.MemberDef , mutable.ListBuffer [Tree ]]()
53+
54+ /** A map from member definitions to their doc comments, so that later
55+ * parallel comment pickling does not need to access symbols of trees (which
56+ * would involve accessing symbols of named types and possibly changing phases
57+ * in doing so).
58+ */
59+ private val docStrings = util.HashTable [untpd.MemberDef , Comment ]()
60+
61+ def treeAnnots (tree : untpd.MemberDef ): List [Tree ] =
62+ val ts = annotTrees.lookup(tree)
63+ if ts == null then Nil else ts.toList
64+
65+ def docString (tree : untpd.MemberDef ): Option [Comment ] =
66+ Option (docStrings.lookup(tree))
67+
4768 private def withLength (op : => Unit ) = {
4869 val lengthAddr = reserveRef(relative = true )
4970 op
@@ -309,7 +330,8 @@ class TreePickler(pickler: TastyPickler) {
309330 if (! tree.isEmpty) pickleTree(tree)
310331 }
311332
312- def pickleDef (tag : Int , sym : Symbol , tpt : Tree , rhs : Tree = EmptyTree , pickleParams : => Unit = ())(using Context ): Unit = {
333+ def pickleDef (tag : Int , mdef : MemberDef , tpt : Tree , rhs : Tree = EmptyTree , pickleParams : => Unit = ())(using Context ): Unit = {
334+ val sym = mdef.symbol
313335 assert(symRefs(sym) == NoAddr , sym)
314336 registerDef(sym)
315337 writeByte(tag)
@@ -321,16 +343,21 @@ class TreePickler(pickler: TastyPickler) {
321343 case _ if tpt.isType => pickleTpt(tpt)
322344 }
323345 pickleTreeUnlessEmpty(rhs)
324- pickleModifiers(sym)
346+ pickleModifiers(sym, mdef )
325347 }
348+ for
349+ docCtx <- ctx.docCtx
350+ comment <- docCtx.docstring(sym)
351+ do
352+ docStrings.enter(mdef, comment)
326353 }
327354
328355 def pickleParam (tree : Tree )(using Context ): Unit = {
329356 registerTreeAddr(tree)
330357 tree match {
331- case tree : ValDef => pickleDef(PARAM , tree.symbol , tree.tpt)
332- case tree : DefDef => pickleDef(PARAM , tree.symbol , tree.tpt, tree.rhs)
333- case tree : TypeDef => pickleDef(TYPEPARAM , tree.symbol , tree.rhs)
358+ case tree : ValDef => pickleDef(PARAM , tree, tree.tpt)
359+ case tree : DefDef => pickleDef(PARAM , tree, tree.tpt, tree.rhs)
360+ case tree : TypeDef => pickleDef(TYPEPARAM , tree, tree.rhs)
334361 }
335362 }
336363
@@ -520,7 +547,7 @@ class TreePickler(pickler: TastyPickler) {
520547 patterns.foreach(pickleTree)
521548 }
522549 case tree : ValDef =>
523- pickleDef(VALDEF , tree.symbol , tree.tpt, tree.rhs)
550+ pickleDef(VALDEF , tree, tree.tpt, tree.rhs)
524551 case tree : DefDef =>
525552 def pickleParamss (paramss : List [List [ValDef ]]): Unit = paramss match
526553 case Nil =>
@@ -531,9 +558,9 @@ class TreePickler(pickler: TastyPickler) {
531558 def pickleAllParams =
532559 pickleParams(tree.tparams)
533560 pickleParamss(tree.vparamss)
534- pickleDef(DEFDEF , tree.symbol , tree.tpt, tree.rhs, pickleAllParams)
561+ pickleDef(DEFDEF , tree, tree.tpt, tree.rhs, pickleAllParams)
535562 case tree : TypeDef =>
536- pickleDef(TYPEDEF , tree.symbol , tree.rhs)
563+ pickleDef(TYPEDEF , tree, tree.rhs)
537564 case tree : Template =>
538565 registerDef(tree.symbol)
539566 writeByte(TEMPLATE )
@@ -648,7 +675,7 @@ class TreePickler(pickler: TastyPickler) {
648675 pickleName(id.name)
649676 }
650677
651- def pickleModifiers (sym : Symbol )(using Context ): Unit = {
678+ def pickleModifiers (sym : Symbol , mdef : MemberDef )(using Context ): Unit = {
652679 import Flags ._
653680 var flags = sym.flags
654681 val privateWithin = sym.privateWithin
@@ -660,7 +687,7 @@ class TreePickler(pickler: TastyPickler) {
660687 if (flags.is(ParamAccessor ) && sym.isTerm && ! sym.isSetter)
661688 flags = flags &~ ParamAccessor // we only generate a tag for parameter setters
662689 pickleFlags(flags, sym.isTerm)
663- sym.annotations.foreach(pickleAnnotation(sym, _))
690+ val annots = sym.annotations.foreach(pickleAnnotation(sym, mdef , _))
664691 }
665692
666693 def pickleFlags (flags : FlagSet , isTerm : Boolean )(using Context ): Unit = {
@@ -723,12 +750,15 @@ class TreePickler(pickler: TastyPickler) {
723750 ann.symbol == defn.BodyAnnot // inline bodies are reconstituted automatically when unpickling
724751 }
725752
726- def pickleAnnotation (owner : Symbol , ann : Annotation )(using Context ): Unit = {
727- if ( ! isUnpicklable(owner, ann)) {
753+ def pickleAnnotation (owner : Symbol , mdef : MemberDef , ann : Annotation )(using Context ): Unit =
754+ if ! isUnpicklable(owner, ann) then
728755 writeByte(ANNOTATION )
729756 withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) }
730- }
731- }
757+ var treeBuf = annotTrees.lookup(mdef)
758+ if treeBuf == null then
759+ treeBuf = new mutable.ListBuffer [Tree ]
760+ annotTrees.enter(mdef, treeBuf)
761+ treeBuf += ann.tree
732762
733763// ---- main entry points ---------------------------------------
734764
0 commit comments