Skip to content

Commit 785fea9

Browse files
committed
Drop uniqueId field in Positioned
Instead, keep a separate weak hashmap if a tree-id option is set. Since tree ids are now only used for debugging, we do not need to maintain them as an inline field anymore.
1 parent 5b39279 commit 785fea9

File tree

5 files changed

+48
-56
lines changed

5 files changed

+48
-56
lines changed

compiler/src/dotty/tools/dotc/Driver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class Driver {
7070
val summary = CompilerCommand.distill(args)(using ictx)
7171
ictx.setSettings(summary.sstate)
7272
MacroClassLoader.init(ictx)
73-
Positioned.updateDebugPos(using ictx)
73+
Positioned.init(using ictx)
7474

7575
inContext(ictx) {
7676
if !ctx.settings.YdropComments.value || ctx.mode.is(Mode.ReadComments) then

compiler/src/dotty/tools/dotc/ast/Positioned.scala

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,34 @@ import java.io.{ PrintWriter }
1919
/** A base class for things that have positions (currently: modifiers and trees)
2020
*/
2121
abstract class Positioned(implicit @constructorOnly src: SourceFile) extends SrcPos, Product, Cloneable {
22+
import Positioned.{ids, nextId, debugId}
2223

2324
private var myUniqueId: Int = _
2425
private var mySpan: Span = _
2526

26-
/** A unique identifier. Among other things, used for determining the source file
27-
* component of the position.
27+
/** A unique identifier in case -Yshow-tree-ids, or -Ydebug-tree-with-id
28+
* is set, -1 otherwise.
2829
*/
29-
def uniqueId: Int = myUniqueId
30+
def uniqueId: Int =
31+
if ids != null && ids.containsKey(this) then ids.get(this) else -1
3032

31-
def uniqueId_=(id: Int): Unit = {
32-
def printTrace() = {
33-
println(s"Debug tree (id=${Positioned.debugId}) creation \n$this\n")
34-
Reporter.displayPrompt(Console.in, new PrintWriter(Console.err, true))
35-
}
36-
if (Positioned.debugId == id) printTrace()
37-
myUniqueId = id
38-
}
33+
private def allocateId() =
34+
if ids != null then
35+
val ownId = nextId
36+
nextId += 1
37+
ids.put(this, ownId)
38+
if ownId == debugId then
39+
println(s"Debug tree (id=$debugId) creation \n$this\n")
40+
Reporter.displayPrompt(Console.in, new PrintWriter(Console.err, true))
41+
42+
allocateId()
3943

4044
/** The span part of the item's position */
4145
def span: Span = mySpan
4246

4347
def span_=(span: Span): Unit =
4448
mySpan = span
4549

46-
uniqueId = src.nextId
4750
span = envelope(src)
4851

4952
val source: SourceFile = src
@@ -125,7 +128,7 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Src
125128
/** Clone this node but assign it a fresh id which marks it as a node in `file`. */
126129
def cloneIn(src: SourceFile): this.type = {
127130
val newpd: this.type = clone.asInstanceOf[this.type]
128-
newpd.uniqueId = src.nextId
131+
newpd.allocateId()
129132
// assert(newpd.uniqueId != 2208, s"source = $this, ${this.uniqueId}, ${this.span}")
130133
newpd
131134
}
@@ -237,8 +240,14 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Src
237240
}
238241

239242
object Positioned {
240-
@sharable private[Positioned] var debugId = Int.MinValue
243+
@sharable private var debugId = Int.MinValue
244+
@sharable private var ids: java.util.WeakHashMap[Positioned, Int] = null
245+
@sharable private var nextId: Int = 0
241246

242-
def updateDebugPos(using Context): Unit =
247+
def init(using Context): Unit =
243248
debugId = ctx.settings.YdebugTreeWithId.value
249+
if ctx.settings.YshowTreeIds.value
250+
|| debugId != ctx.settings.YdebugTreeWithId.default
251+
then
252+
ids = java.util.WeakHashMap()
244253
}

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ object Trees {
221221
}
222222
}
223223

224-
override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this)
224+
override def hashCode(): Int = System.identityHashCode(this)
225225
override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
226226
}
227227

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ object Inliner {
7070
* and body that replace it.
7171
*/
7272
def inlineCall(tree: Tree)(using Context): Tree = {
73-
val startId = ctx.source.nextId
74-
7573
if tree.symbol.denot != SymDenotations.NoDenotation
7674
&& tree.symbol.owner.companionModule == defn.CompiletimeTestingPackageObject
7775
then
@@ -136,10 +134,6 @@ object Inliner {
136134
|You can use ${setting.name} to change the limit.""",
137135
(tree :: enclosingInlineds).last.srcPos
138136
)
139-
140-
val endId = ctx.source.nextId
141-
addInlinedTrees(endId - startId)
142-
143137
tree2
144138
}
145139

@@ -735,6 +729,26 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
735729
case _ =>
736730
}
737731

732+
/** The number of nodes in this tree, excluding code in nested inline
733+
* calls and annotations of definitions.
734+
*/
735+
def treeSize(x: Any): Int =
736+
var siz = 0
737+
x match
738+
case x: Trees.Inlined[_] =>
739+
case x: Positioned =>
740+
var i = 0
741+
while i < x.productArity do
742+
siz += treeSize(x.productElement(i))
743+
i += 1
744+
case x: List[_] =>
745+
var xs = x
746+
while xs.nonEmpty do
747+
siz += treeSize(xs.head)
748+
xs = xs.tail
749+
case _ =>
750+
siz
751+
738752
trace(i"inlining $call", inlining, show = true) {
739753

740754
// The normalized bindings collected in `bindingsBuf`
@@ -758,6 +772,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
758772

759773
if (inlinedMethod == defn.Compiletime_error) issueError()
760774

775+
addInlinedTrees(treeSize(finalExpansion))
776+
761777
// Take care that only argument bindings go into `bindings`, since positions are
762778
// different for bindings from arguments and bindings from body.
763779
tpd.Inlined(call, finalBindings, finalExpansion)

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

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -181,49 +181,16 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends
181181
}
182182

183183
override def toString: String = file.toString
184-
185-
// Positioned ids
186-
187-
private val ctr = new AtomicInteger
188-
189-
def nextId: Int = {
190-
val id = ctr.get
191-
if (id % ChunkSize == 0) newChunk
192-
else if (ctr.compareAndSet(id, id + 1)) id
193-
else nextId
194-
}
195-
196-
private def newChunk: Int = sourceOfChunk.synchronized {
197-
val id = chunks << ChunkSizeLog
198-
if (chunks == sourceOfChunk.length) {
199-
val a = new Array[SourceFile](chunks * 2)
200-
System.arraycopy(sourceOfChunk, 0, a, 0, chunks)
201-
sourceOfChunk = a
202-
}
203-
sourceOfChunk(chunks) = this
204-
chunks += 1
205-
ctr.set(id + 1)
206-
id
207-
}
208184
}
209185
object SourceFile {
210186
implicit def eqSource: Eql[SourceFile, SourceFile] = Eql.derived
211187

212188
implicit def fromContext(using Context): SourceFile = ctx.source
213189

214-
def fromId(id: Int): SourceFile = sourceOfChunk(id >> ChunkSizeLog)
215-
216190
def virtual(name: String, content: String, maybeIncomplete: Boolean = false) =
217191
val src = new SourceFile(new VirtualFile(name, content.getBytes(StandardCharsets.UTF_8)), scala.io.Codec.UTF8)
218192
src._maybeInComplete = maybeIncomplete
219193
src
220-
221-
private final val ChunkSizeLog = 10
222-
private final val ChunkSize = 1 << ChunkSizeLog
223-
224-
// These two vars are sharable because they're only used in the synchronized block in newChunk
225-
@sharable private var chunks: Int = 0
226-
@sharable private var sourceOfChunk: Array[SourceFile] = new Array[SourceFile](2000)
227194
}
228195

229196
@sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) {

0 commit comments

Comments
 (0)