Skip to content

Commit c7106ef

Browse files
committed
Put line sizes in the Positions section
1 parent c36a3e0 commit c7106ef

File tree

12 files changed

+62
-133
lines changed

12 files changed

+62
-133
lines changed

compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala

+5-11
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,17 @@ object DottyUnpickler {
1818
/** Exception thrown if classfile is corrupted */
1919
class BadSignature(msg: String) extends RuntimeException(msg)
2020

21-
class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], lineSizesUnpickler: Option[LineSizesUnpickler], commentUnpickler: Option[CommentUnpickler])
21+
class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], commentUnpickler: Option[CommentUnpickler])
2222
extends SectionUnpickler[TreeUnpickler](ASTsSection) {
2323
def unpickle(reader: TastyReader, nameAtRef: NameTable): TreeUnpickler =
24-
new TreeUnpickler(reader, nameAtRef, posUnpickler, lineSizesUnpickler, commentUnpickler)
24+
new TreeUnpickler(reader, nameAtRef, posUnpickler, commentUnpickler)
2525
}
2626

2727
class PositionsSectionUnpickler extends SectionUnpickler[PositionUnpickler](PositionsSection) {
2828
def unpickle(reader: TastyReader, nameAtRef: NameTable): PositionUnpickler =
2929
new PositionUnpickler(reader, nameAtRef)
3030
}
3131

32-
class LineSizesSectionUnpickler extends SectionUnpickler[LineSizesUnpickler]("LineSizes") {
33-
def unpickle(reader: TastyReader, nameAtRef: NameTable): LineSizesUnpickler =
34-
new LineSizesUnpickler(reader)
35-
}
36-
3732
class CommentsSectionUnpickler extends SectionUnpickler[CommentUnpickler](CommentsSection) {
3833
def unpickle(reader: TastyReader, nameAtRef: NameTable): CommentUnpickler =
3934
new CommentUnpickler(reader)
@@ -50,18 +45,17 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe
5045

5146
val unpickler: TastyUnpickler = new TastyUnpickler(bytes)
5247
private val posUnpicklerOpt = unpickler.unpickle(new PositionsSectionUnpickler)
53-
private val lineSizesUnpicklerOpt = unpickler.unpickle(new LineSizesSectionUnpickler)
5448
private val commentUnpicklerOpt = unpickler.unpickle(new CommentsSectionUnpickler)
55-
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, lineSizesUnpicklerOpt, commentUnpicklerOpt)).get
49+
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt)).get
5650

5751
/** Enter all toplevel classes and objects into their scopes
5852
* @param roots a set of SymDenotations that should be overwritten by unpickling
5953
*/
6054
def enter(roots: Set[SymDenotation])(using Context): Unit =
6155
treeUnpickler.enter(roots)
6256

63-
protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], lineSizesUnpicklerOpt: Option[LineSizesUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler =
64-
new TreeSectionUnpickler(posUnpicklerOpt, lineSizesUnpicklerOpt, commentUnpicklerOpt)
57+
protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler =
58+
new TreeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt)
6559

6660
protected def computeRootTrees(using Context): List[Tree] = treeUnpickler.unpickle(mode)
6761

compiler/src/dotty/tools/dotc/core/tasty/LineSizesPickler.scala

-35
This file was deleted.

compiler/src/dotty/tools/dotc/core/tasty/LineSizesUnpickler.scala

-45
This file was deleted.

compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala

+15-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,21 @@ class PositionPickler(
3232
(addrDelta << 3) | (toInt(hasStartDelta) << 2) | (toInt(hasEndDelta) << 1) | toInt(hasPoint)
3333
}
3434

35-
def picklePositions(roots: List[Tree], warnings: mutable.ListBuffer[String]): Unit = {
35+
def picklePositions(source: SourceFile, roots: List[Tree], warnings: mutable.ListBuffer[String]): Unit = {
36+
/** Pickle the number of lines followed by the length of each line */
37+
def pickleLineOffsetts(): Unit = {
38+
val content = source.content()
39+
buf.writeInt(content.count(_ == '\n') + 1) // number of lines
40+
var lastIndex = content.indexOf('\n', 0)
41+
buf.writeInt(lastIndex) // size of first line
42+
while lastIndex != -1 do
43+
val nextIndex = content.indexOf('\n', lastIndex + 1)
44+
val end = if nextIndex != -1 then nextIndex else content.length
45+
buf.writeInt(end - lastIndex - 1) // size of the next line
46+
lastIndex = nextIndex
47+
}
48+
pickleLineOffsetts()
49+
3650
var lastIndex = 0
3751
var lastSpan = Span(0, 0)
3852
def pickleDeltas(index: Int, span: Span) = {

compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala

+13
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@ import Names.TermName
1515
class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) {
1616
import reader._
1717

18+
private var myLineSizes: Array[Int] = _
1819
private var mySpans: util.HashMap[Addr, Span] = _
1920
private var mySourcePaths: util.HashMap[Addr, String] = _
2021
private var isDefined = false
2122

2223
def ensureDefined(): Unit = {
2324
if (!isDefined) {
25+
val lines = readInt()
26+
myLineSizes = new Array[Int](lines)
27+
var i = 0
28+
while i < lines do
29+
myLineSizes(i) += readInt()
30+
i += 1
31+
2432
mySpans = util.HashMap[Addr, Span]()
2533
mySourcePaths = util.HashMap[Addr, String]()
2634
var curIndex = 0
@@ -60,6 +68,11 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) {
6068
mySourcePaths
6169
}
6270

71+
private[tasty] def lineSizes: Array[Int] = {
72+
ensureDefined()
73+
myLineSizes
74+
}
75+
6376
def spanAt(addr: Addr): Span = spans.getOrElse(addr, NoSpan)
6477
def sourcePathAt(addr: Addr): String = sourcePaths.getOrElse(addr, "")
6578
}

compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala

+6-20
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ class TastyPrinter(bytes: Array[Byte]) {
5151
case _ =>
5252
}
5353
sb.append("\n\n")
54-
unpickle(new LineSizesSectionUnpickler) match {
55-
case Some(s) => sb.append(s)
56-
case _ =>
57-
}
58-
sb.append("\n\n")
5954
unpickle(new CommentSectionUnpickler) match {
6055
case Some(s) => sb.append(s)
6156
case _ =>
@@ -144,9 +139,14 @@ class TastyPrinter(bytes: Array[Byte]) {
144139
private val sb: StringBuilder = new StringBuilder
145140

146141
def unpickle(reader: TastyReader, tastyName: NameTable): String = {
142+
val posUnpickler = new PositionUnpickler(reader, tastyName)
147143
sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}")
148-
val spans = new PositionUnpickler(reader, tastyName).spans
149144
sb.append(" position bytes:\n")
145+
val lineSizes = posUnpickler.lineSizes
146+
sb.append(s" lines: ${lineSizes.length}\n")
147+
sb.append(posUnpickler.lineSizes.mkString(" line sizes: ", ", ", "\n"))
148+
sb.append(" positions:\n")
149+
val spans = posUnpickler.spans
150150
val sorted = spans.toSeq.sortBy(_._1.index)
151151
for ((addr, pos) <- sorted) {
152152
sb.append(treeStr("%10d".format(addr.index)))
@@ -156,20 +156,6 @@ class TastyPrinter(bytes: Array[Byte]) {
156156
}
157157
}
158158

159-
class LineSizesSectionUnpickler extends SectionUnpickler[String]("LineSizes") {
160-
161-
private val sb: StringBuilder = new StringBuilder
162-
163-
def unpickle(reader: TastyReader, tastyName: NameTable): String = {
164-
sb.append(" ").append(reader.endAddr.index - reader.currentAddr.index)
165-
sb.append(" line sizes bytes:\n")
166-
val lineSizes = new LineSizesUnpickler(reader)
167-
sb.append(" sizes: ")
168-
sb.append(lineSizes.sizes.mkString(", "))
169-
sb.result
170-
}
171-
}
172-
173159
class CommentSectionUnpickler extends SectionUnpickler[String](CommentsSection) {
174160

175161
private val sb: StringBuilder = new StringBuilder

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

+6-8
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,13 @@ import scala.annotation.constructorOnly
4747
import scala.annotation.internal.sharable
4848

4949
/** Unpickler for typed trees
50-
* @param reader the reader from which to unpickle
51-
* @param posUnpicklerOpt the unpickler for positions, if it exists
52-
* @param lineSizesUnpicklerOpt the unpickler for line sizes, if it exists
53-
* @param commentUnpicklerOpt the unpickler for comments, if it exists
50+
* @param reader the reader from which to unpickle
51+
* @param posUnpicklerOpt the unpickler for positions, if it exists
52+
* @param commentUnpicklerOpt the unpickler for comments, if it exists
5453
*/
5554
class TreeUnpickler(reader: TastyReader,
5655
nameAtRef: NameTable,
5756
posUnpicklerOpt: Option[PositionUnpickler],
58-
lineSizesUnpicklerOpt: Option[LineSizesUnpickler],
5957
commentUnpicklerOpt: Option[CommentUnpickler]) {
6058
import TreeUnpickler._
6159
import tpd._
@@ -1366,9 +1364,9 @@ class TreeUnpickler(reader: TastyReader,
13661364
val path = sourcePathAt(addr)
13671365
if (path.nonEmpty) {
13681366
val sourceFile = ctx.getSource(path)
1369-
lineSizesUnpicklerOpt match
1370-
case Some(lineSizesUnpickler) =>
1371-
sourceFile.setLineIndices(lineSizesUnpickler.lineIndices)
1367+
posUnpicklerOpt match
1368+
case Some(posUnpickler) =>
1369+
sourceFile.setLineIndicesFromLineSizes(posUnpickler.lineSizes)
13721370
case _ =>
13731371
pickling.println(i"source change at $addr: $path")
13741372
ctx.withSource(sourceFile)

compiler/src/dotty/tools/dotc/quoted/PickledQuotes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ object PickledQuotes {
168168
if tree.span.exists then
169169
val positionWarnings = new mutable.ListBuffer[String]()
170170
new PositionPickler(pickler, treePkl.buf.addrOfTree, treePkl.treeAnnots)
171-
.picklePositions(tree :: Nil, positionWarnings)
171+
.picklePositions(ctx.compilationUnit.source, tree :: Nil, positionWarnings)
172172
positionWarnings.foreach(report.warning(_))
173173

174174
val pickled = pickler.assembleParts()

compiler/src/dotty/tools/dotc/transform/Pickler.scala

+1-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ class Pickler extends Phase {
7373
treePkl.compactify()
7474
if tree.span.exists then
7575
new PositionPickler(pickler, treePkl.buf.addrOfTree, treePkl.treeAnnots)
76-
.picklePositions(tree :: Nil, positionWarnings)
77-
new LineSizesPickler(pickler)
78-
.pickleLineNumbers(unit.source)
76+
.picklePositions(unit.source, tree :: Nil, positionWarnings)
7977

8078
if !ctx.settings.YdropComments.value then
8179
new CommentPickler(pickler, treePkl.buf.addrOfTree, treePkl.docString)

compiler/src/dotty/tools/dotc/util/SourceFile.scala

+9-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,15 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends
129129
if lineIndicesCache eq null then
130130
lineIndicesCache = calculateLineIndicesFromContents()
131131
lineIndicesCache
132-
def setLineIndices(indices: Array[Int]): Unit =
132+
def setLineIndicesFromLineSizes(sizes: Array[Int]): Unit =
133+
val lines = sizes.length
134+
val indices = new Array[Int](lines + 1)
135+
var i = 0
136+
val penultimate = lines - 1
137+
while i < penultimate do
138+
indices(i + 1) = indices(i) + sizes(i) + 1 // `+1` for the '\n' at the end of the line
139+
i += 1
140+
indices(lines) = indices(penultimate) + sizes(penultimate) // last line does not end with '\n'
133141
lineIndicesCache = indices
134142

135143
/** Map line to offset of first character in line */

project/scripts/cmdTests

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ cp tests/neg/i6371/B_2.scala $OUT/B.scala
5252
rm $OUT/A.scala
5353
"$SBT" "scalac -classpath $OUT1 -d $OUT1 $OUT/B.scala" > "$tmp" 2>&1 || echo "ok"
5454
grep -qe "B.scala:2:7" "$tmp"
55+
grep -qe "This location contains code that was inlined from A.scala:3" "$tmp"
5556

5657
echo "testing -Ythrough-tasty"
5758
clear_out "$OUT"

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

+5-8
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ Note: Tree tags are grouped into 5 categories that determine what follows, and t
228228
Category 5 (tags 128-255): tag Length <payload>
229229
230230
231-
Standard-Section: "Positions" Assoc*
231+
Standard-Section: "Positions" LinesSizes Assoc*
232+
233+
LinesSizes = Int Int* // Number of lines followed by the size of each line not counting the trailing `\n`
232234
233235
Assoc = Header offset_Delta? offset_Delta? point_Delta?
234236
| SOURCE nameref_Int
@@ -247,11 +249,6 @@ Standard-Section: "Positions" Assoc*
247249
All elements of a position section are serialized as Ints
248250
249251
250-
Standard-Section: "LineSizes" LineSize*
251-
252-
LineSize = Int // Size the i-th line not counting the trailing `\n`
253-
254-
255252
Standard Section: "Comments" Comment*
256253
257254
Comment = Length Bytes LongInt // Raw comment's bytes encoded as UTF-8, followed by the comment's coordinates.
@@ -262,8 +259,8 @@ Standard Section: "Comments" Comment*
262259
object TastyFormat {
263260

264261
final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F)
265-
val MajorVersion: Int = 25
266-
val MinorVersion: Int = 1
262+
val MajorVersion: Int = 26
263+
val MinorVersion: Int = 0
267264

268265
final val ASTsSection = "ASTs"
269266
final val PositionsSection = "Positions"

0 commit comments

Comments
 (0)