Skip to content

Commit 7f08c1f

Browse files
committed
Maintain ownerTree data structure when unpickling Tasty
First step for a more robust scheme to access symbols in Tasty. This entailed a swap of two fields in RefiendType, to make tree format more uniform in what concerns where references are found.
1 parent 1f8cf78 commit 7f08c1f

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,4 +485,15 @@ object TastyFormat {
485485
case PRIVATEqualified => "PRIVATEqualified"
486486
case PROTECTEDqualified => "PROTECTEDqualified"
487487
}
488+
489+
/** @return If non-negative, the number of leading references of a length/trees entry.
490+
* If negative, minus the number of leading non-reference trees.
491+
*/
492+
def numRefs(tag: Int) = tag match {
493+
case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND |
494+
SELFDEF | REFINEDtype => 1
495+
case RENAMED | PARAMtype => 2
496+
case POLYtype | METHODtype => -1
497+
case _ => 0
498+
}
488499
}

src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ class TreePickler(pickler: TastyPickler) {
217217
case tpe: RefinedType =>
218218
writeByte(REFINEDtype)
219219
withLength {
220-
pickleType(tpe.parent)
221220
pickleName(tpe.refinedName)
221+
pickleType(tpe.parent)
222222
pickleType(tpe.refinedInfo, richTypes = true)
223223
}
224224
case tpe: TypeAlias =>

src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
5757

5858
private var roots: Set[SymDenotation] = null
5959

60+
private var ownerTree: OwnerTree = _
61+
6062
private def registerSym(addr: Addr, sym: Symbol) = {
6163
symAtAddr(addr) = sym
6264
unpickledSyms += sym
@@ -118,6 +120,45 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
118120
def skipParams(): Unit =
119121
while (nextByte == PARAMS || nextByte == TYPEPARAM) skipTree()
120122

123+
/** Record all directly nested definitions and templates in current tree
124+
* as `OwnerTree`s in `buf`
125+
*/
126+
def scanTree(buf: ListBuffer[OwnerTree]): Unit = {
127+
val start = currentAddr
128+
val tag = readByte()
129+
//println(s"scan tree at $currentAddr, tag = $tag")
130+
tag match {
131+
case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | TEMPLATE =>
132+
val end = readEnd()
133+
for (i <- 0 until numRefs(tag)) readNat()
134+
buf += new OwnerTree(start, fork, end)
135+
case tag =>
136+
if (tag >= firstLengthTreeTag) {
137+
val end = readEnd()
138+
var nrefs = numRefs(tag)
139+
if (nrefs < 0) {
140+
for (i <- nrefs until 0) scanTree(buf)
141+
goto(end)
142+
}
143+
else {
144+
for (i <- 0 until nrefs) readNat()
145+
scanTrees(buf, end)
146+
}
147+
}
148+
else if (tag >= firstNatASTTreeTag) { readNat(); scanTree(buf) }
149+
else if (tag >= firstASTTreeTag) scanTree(buf)
150+
else if (tag >= firstNatTreeTag) readNat()
151+
}
152+
}
153+
154+
/** Record all directly nested definitions and templates between current address and `end`
155+
* as `OwnerTree`s in `buf`
156+
*/
157+
def scanTrees(buf: ListBuffer[OwnerTree], end: Addr): Unit = {
158+
while (currentAddr.index < end.index) scanTree(buf)
159+
assert(currentAddr.index == end.index)
160+
}
161+
121162
/** The next tag, following through SHARED tags */
122163
def nextUnsharedTag: Int = {
123164
val tag = nextByte
@@ -197,8 +238,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
197238
case SUPERtype =>
198239
SuperType(readType(), readType())
199240
case REFINEDtype =>
200-
val parent = readType()
201241
var name: Name = readName()
242+
val parent = readType()
202243
val ttag = nextUnsharedTag
203244
if (ttag == TYPEBOUNDS || ttag == TYPEALIAS) name = name.toTypeName
204245
RefinedType(parent, name, rt => registeringType(rt, readType()))
@@ -437,7 +478,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
437478
}
438479

439480
/** Read modifier list into triplet of flags, annotations and a privateWithin
440-
* boindary symbol.
481+
* boundary symbol.
441482
*/
442483
def readModifiers(end: Addr)(implicit ctx: Context): (FlagSet, List[Annotation], Symbol) = {
443484
var flags: FlagSet = EmptyFlags
@@ -664,6 +705,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
664705
else NoType
665706
setClsInfo(Nil, assumedSelfType)
666707
val localDummy = ctx.newLocalDummy(cls)
708+
registerSym(start, localDummy)
667709
assert(readByte() == TEMPLATE)
668710
val end = readEnd()
669711
val tparams = readIndexedParams[TypeDef](TYPEPARAM)
@@ -716,12 +758,11 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
716758
}
717759

718760
def readTopLevel()(implicit ctx: Context): List[Tree] = {
761+
ownerTree = new OwnerTree(NoAddr, fork, reader.endAddr)
719762
@tailrec def read(acc: ListBuffer[Tree]): List[Tree] = nextByte match {
720763
case IMPORT | PACKAGE =>
721764
acc += readIndexedStat(NoSymbol)
722-
if (!isAtEnd)
723-
read(acc)
724-
else acc.toList
765+
if (!isAtEnd) read(acc) else acc.toList
725766
case _ => // top-level trees which are not imports or packages are not part of tree
726767
acc.toList
727768
}
@@ -968,4 +1009,33 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
9681009
res
9691010
}
9701011
}
1012+
1013+
class OwnerTree(val addr: Addr, reader: TreeReader, val end: Addr) {
1014+
lazy val children: List[OwnerTree] = {
1015+
val buf = new ListBuffer[OwnerTree]
1016+
reader.scanTrees(buf, end)
1017+
buf.toList
1018+
}
1019+
def findOwner(addr: Addr)(implicit ctx: Context): Symbol = {
1020+
//println(s"find owner $addr")
1021+
def search(cs: List[OwnerTree], current: Symbol): Symbol = cs match {
1022+
case ot :: cs1 =>
1023+
if (ot.addr.index == addr.index) {
1024+
//println(i"search ok $addr, owner = $current")
1025+
current
1026+
}
1027+
else if (ot.addr.index < addr.index && addr.index < ot.end.index) {
1028+
val encl = reader.symbolAt(ot.addr)
1029+
//println(s"search $addr in ${ot.children} with $encl")
1030+
search(ot.children, encl)
1031+
}
1032+
else
1033+
search(cs1, current)
1034+
case Nil =>
1035+
throw new Error("unattached tree")
1036+
}
1037+
search(children, NoSymbol)
1038+
}
1039+
override def toString = s"OwnerTree(${addr.index}, ${end.index}"
1040+
}
9711041
}

0 commit comments

Comments
 (0)