Skip to content

Commit 69b2b23

Browse files
committed
Use Inlined nodes' information instead of using attachements
1 parent 3e18e2c commit 69b2b23

File tree

2 files changed

+48
-90
lines changed

2 files changed

+48
-90
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -583,24 +583,17 @@ trait BCodeSkelBuilder extends BCodeHelpers {
583583
end emitNr
584584

585585
def lineNumber(tree: Tree): Unit = {
586-
587586
if (!emitLines || !tree.span.exists) return;
588-
if tree.source != cunit.source then
589-
tree.getAttachment(InliningPosition) match
590-
case Some(pos) =>
591-
val sourcePosition = pos.targetPos.find(p => p._1.source == cunit.source)
592-
if sourcePosition.nonEmpty then
593-
val offset = sourcePosition.get._1.span.point
594-
lastRealLineNr = ctx.source.offsetToLine(offset) + 1
595-
case None => ()
596-
sourceMap.lineFor(tree.sourcePos, lastRealLineNr, tree.getAttachment(InliningPosition)) match
587+
// Use JSR-45 mapping for inlined trees defined outside of the current compilation unit
588+
if tree.source != cunit.source || (tree.isInstanceOf[Inlined] && tree.asInstanceOf[Inlined].expansion.source != cunit.source) then
589+
sourceMap.lineFor(tree) match
597590
case Some(nr) =>
598-
emitNr(nr)
591+
return emitNr(nr)
599592
case None => ()
600593
else
601594
val nr = ctx.source.offsetToLine(tree.span.point) + 1
602595
lastRealLineNr = nr
603-
emitNr(nr)
596+
return emitNr(nr)
604597
}
605598

606599
// on entering a method

compiler/src/dotty/tools/backend/jvm/InlinedSourceMaps.scala

Lines changed: 43 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import collection.mutable
3333
* stack frames for inlined calls.
3434
**/
3535
object InlinedSourceMaps:
36-
private case class Request(targetPos: SourcePosition, origPos: SourcePosition, firstFakeLine: Int)
36+
//private case class Request(targetPos: SourcePosition, origPos: SourcePosition, firstFakeLine: Int)
37+
private case class Request(inline: Inlined, firstFakeLine: Int)
3738

3839
private class File(id: Int, name: String, path: Option[String]):
3940
def write(b: mutable.StringBuilder): Unit =
@@ -81,37 +82,29 @@ object InlinedSourceMaps:
8182
b ++= "*E\n"
8283
end Stratum
8384

84-
//targetPos is the position of the inlined call inlined(5)
85-
//origPos is the position of the inlined code inline def inlined(arg) { ... }
8685
def sourceMapFor(cunit: CompilationUnit)(internalNameProvider: Symbol => String)(using Context): InlinedSourceMap =
87-
val requests = mutable.ListBuffer.empty[(SourcePosition, SourcePosition)]
86+
val requests = mutable.ListBuffer.empty[Inlined]
8887
var internalNames = Map.empty[SourceFile, String]
8988

9089
class RequestCollector(enclosingFile: SourceFile) extends TreeTraverser:
9190
override def traverse(tree: Tree)(using Context): Unit =
92-
if tree.hasAttachment(InliningPosition) then
93-
tree.getAttachment(InliningPosition) match
94-
case Some(InliningPosition(l)) =>
95-
l.foreach {
96-
(targetPos, cls) =>
97-
if tree.source != enclosingFile && tree.source != cunit.source then
98-
requests += (targetPos -> tree.sourcePos)
99-
100-
cls match
101-
case Some(symbol) if !internalNames.isDefinedAt(tree.source) =>
102-
internalNames += (tree.source -> internalNameProvider(symbol))
103-
// We are skipping any internal name info if we already have one stored in our map
104-
// because a debugger will use internal name only to localize matching source.
105-
// Both old and new internal names are associated with the same source file
106-
// so it doesn't matter if internal name is not matching used symbol.
107-
case _ => ()
108-
}
109-
traverseChildren(tree)
110-
case None =>
111-
// Not exactly sure in which cases it is happening. Should we report warning?
112-
traverseChildren(tree)
113-
else
114-
traverseChildren(tree)
91+
tree match
92+
case Inlined(call, bindings, expansion) =>
93+
if expansion.source != enclosingFile && expansion.source != cunit.source then
94+
requests += tree.asInstanceOf[Inlined]
95+
val topLevelClass = Option.when(!call.isEmpty)(call.symbol.topLevelClass)
96+
97+
topLevelClass match
98+
case Some(symbol) if !internalNames.isDefinedAt(tree.source) =>
99+
internalNames += (tree.source -> internalNameProvider(symbol))
100+
// We are skipping any internal name info if we already have one stored in our map
101+
// because a debugger will use internal name only to localize matching source.
102+
// Both old and new internal names are associated with the same source file
103+
// so it doesn't matter if internal name is not matching used symbol.
104+
case _ => ()
105+
106+
traverseChildren(tree)
107+
case _ => traverseChildren(tree)
115108
end RequestCollector
116109

117110
// Don't generate mappings for the quotes compiled at runtime by the staging compiler
@@ -126,7 +119,7 @@ object InlinedSourceMaps:
126119

127120
RequestCollector(cunit.source).traverse(cunit.tpdTree)
128121

129-
val allocated = requests.map(r => Request(r._1, r._2, allocate(r._2)))
122+
val allocated = requests.map(r => Request(r, allocate(r.expansion.sourcePos)))
130123

131124
InlinedSourceMap(cunit, allocated.toList, internalNames)
132125
end sourceMapFor
@@ -136,53 +129,25 @@ object InlinedSourceMaps:
136129
requests: List[Request],
137130
internalNames: Map[SourceFile, String])(using Context):
138131

139-
def debugExtension: Option[String] = Option.when(requests.nonEmpty) {
140-
val scalaStratum =
141-
val files = cunit.source :: requests.map(_.origPos.source).distinct.filter(_ != cunit.source)
142-
val mappings = requests.map { case Request(_, origPos, firstFakeLine) =>
143-
Mapping(origPos.startLine, files.indexOf(origPos.source) + 1, origPos.lines.length, firstFakeLine, 1)
144-
}
145-
Stratum("Scala",
146-
files.zipWithIndex.map { case (f, n) => File(n + 1, f.name, internalNames.get(f)) },
147-
Mapping(0, 1, cunit.tpdTree.sourcePos.lines.length, 0, 1) +: mappings
148-
)
149-
150-
val debugStratum =
151-
val mappings = requests.map { case Request(targetPos, origPos, firstFakeLine) =>
152-
Mapping(targetPos.startLine, 1, 1, firstFakeLine, origPos.lines.length)
153-
}
154-
Stratum("ScalaDebug", File(1, cunit.source.name, None) :: Nil, mappings)
155-
156-
val b = new StringBuilder
157-
b ++= "SMAP\n"
158-
b ++= cunit.source.name
159-
b += '\n'
160-
b ++= "Scala\n"
161-
scalaStratum.write(b)
162-
debugStratum.write(b)
163-
b.toString
164-
}
165-
166-
var lastNestedInlineLine = -1
167-
168-
def lineFor(sourcePos: SourcePosition, lastRealNr: Int, attachement: Option[InliningPosition]): Option[Int] =
169-
170-
if attachement.isDefined then
171-
attachement.get.targetPos.find(p => p._1.source == sourcePos.source) match
172-
case Some((pos, _)) =>
173-
lastNestedInlineLine = pos.startLine
174-
case None => ()
175-
176-
requests.find(r =>
177-
r.origPos.contains(sourcePos) &&
178-
(if r.targetPos.source == cunit.source then r.targetPos.endLine + 1 >= lastRealNr
179-
else r.targetPos.startLine >= lastNestedInlineLine
180-
)
181-
) match
182-
case Some(request) =>
183-
val offset = sourcePos.startLine - request.origPos.startLine
184-
val virtualLine = request.firstFakeLine + offset
185-
Some(virtualLine + 1) // + 1 because the first line is 1 in the LineNumberTable
186-
case None =>
187-
// report.warning(s"${sourcePos.show} was inlined in ${cunit.source} but its inlining position was not recorded.")
188-
None
132+
def debugExtension: Option[String] = Some("TODO")
133+
134+
private val inlines = mutable.ListBuffer.empty[Inlined]
135+
136+
def lineFor(tree: Tree): Option[Int] =
137+
138+
tree match
139+
case Inlined(call, binding, expansion) =>
140+
inlines += tree.asInstanceOf[Inlined]
141+
None
142+
case _ =>
143+
val sourcePos = tree.sourcePos
144+
val inline = inlines.findLast(_.expansion.contains(tree))
145+
requests.findLast(r => r.inline.expansion.contains(tree)) match
146+
case Some(request) =>
147+
val offset = sourcePos.startLine - request.inline.expansion.sourcePos.startLine
148+
val virtualLine = request.firstFakeLine + offset
149+
if requests.filter(_.inline.expansion.contains(tree)).size > 1 then None
150+
else Some(virtualLine + 1) // + 1 because the first line is 1 in the LineNumberTable
151+
case None =>
152+
// report.warning(s"${sourcePos.show} was inlined in ${cunit.source} but its inlining position was not recorded.")
153+
None

0 commit comments

Comments
 (0)