Skip to content

Commit 3bcabcb

Browse files
committed
Break up Symbol.info for JIT friendliness
Also remove commented out debugging code and simplify adaptInfos.
1 parent a5cb5d6 commit 3bcabcb

File tree

1 file changed

+85
-88
lines changed

1 file changed

+85
-88
lines changed

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 85 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
3636

3737
protected def nextId() = { ids += 1; ids }
3838

39-
/** Used for deciding in the IDE whether we can interrupt the compiler */
40-
//protected var activeLocks = 0
41-
42-
/** Used for debugging only */
43-
//protected var lockedSyms = scala.collection.immutable.Set[Symbol]()
44-
4539
/** Used to keep track of the recursion depth on locked symbols */
4640
private[this] var _recursionTable = immutable.Map.empty[Symbol, Int]
4741
def recursionTable = _recursionTable
@@ -589,16 +583,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
589583
} else {
590584
_rawflags |= LOCKED
591585
true
592-
// activeLocks += 1
593-
// lockedSyms += this
594586
}
595587
}
596588

597589
// Unlock a symbol
598590
private[scala] def unlock() = {
599591
if ((_rawflags & LOCKED) != 0L) {
600-
// activeLocks -= 1
601-
// lockedSyms -= this
602592
_rawflags &= ~LOCKED
603593
if (settings.Yrecursion.value != 0)
604594
recursionTable -= this
@@ -1521,41 +1511,42 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
15211511
/** Get type info associated with symbol at current phase, after
15221512
* ensuring that symbol is initialized (i.e. type is completed).
15231513
*/
1524-
def info: Type = try {
1514+
def info: Type = {
15251515
var cnt = 0
1526-
while (validTo == NoPeriod) {
1527-
assert(infos ne null, this.name)
1528-
assert(infos.prev eq null, this.name)
1529-
val tp = infos.info
1530-
1531-
if ((_rawflags & LOCKED) != 0L) { // rolled out once for performance
1532-
lock {
1533-
setInfo(ErrorType)
1534-
throw CyclicReference(this, tp)
1535-
}
1536-
} else {
1537-
_rawflags |= LOCKED
1538-
// TODO another commented out lines - this should be solved in one way or another
1539-
// activeLocks += 1
1540-
// lockedSyms += this
1541-
}
1542-
val current = phase
1543-
try {
1544-
assertCorrectThread()
1545-
phase = phaseOf(infos.validFrom)
1546-
tp.complete(this)
1547-
} finally {
1548-
unlock()
1549-
phase = current
1550-
}
1516+
while (_validTo == NoPeriod) {
1517+
completeInfo()
15511518
cnt += 1
15521519
// allow for two completions:
15531520
// one: sourceCompleter to LazyType, two: LazyType to completed type
1554-
if (cnt == 3) abort(s"no progress in completing $this: $tp")
1521+
def abortNoProgress() = abort(s"no progress in completing $this: ${infos.info}")
1522+
if (cnt == 3) abortNoProgress()
15551523
}
15561524
rawInfo
15571525
}
1558-
catch {
1526+
1527+
private def completeInfo(): Unit = try {
1528+
assert(infos ne null, this.name)
1529+
assert(infos.prev eq null, this.name)
1530+
val tp = infos.info
1531+
1532+
if ((_rawflags & LOCKED) != 0L) { // rolled out once for performance
1533+
lock {
1534+
setInfo(ErrorType)
1535+
throw CyclicReference(this, tp)
1536+
}
1537+
} else {
1538+
_rawflags |= LOCKED
1539+
}
1540+
val current = phase
1541+
try {
1542+
assertCorrectThread()
1543+
phase = phaseOf(infos.validFrom)
1544+
tp.complete(this)
1545+
} finally {
1546+
unlock()
1547+
phase = current
1548+
}
1549+
} catch {
15591550
case ex: CyclicReference =>
15601551
devWarning("... hit cycle trying to complete " + this.fullLocationString)
15611552
throw ex
@@ -1611,81 +1602,87 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
16111602

16121603
/** Return info without checking for initialization or completing */
16131604
def rawInfo: Type = {
1605+
// OPT: hoisting the outer reference reduces the bytecode size of this method a little which makes it more
1606+
// likely to inline into hot callers of .info
1607+
val outer = Symbols.this
1608+
16141609
var infos = this.infos
1615-
assert(infos != null)
1616-
val curPeriod = currentPeriod
1617-
val curPid = phaseId(curPeriod)
1610+
outer.assert(infos != null)
1611+
1612+
if (_validTo != NoPeriod) {
1613+
val curPeriod = outer.currentPeriod
1614+
val curPid = outer.phaseId(curPeriod)
16181615

1619-
if (validTo != NoPeriod) {
16201616
// skip any infos that concern later phases
1621-
while (curPid < phaseId(infos.validFrom) && infos.prev != null)
1617+
while (curPid < outer.phaseId(infos.validFrom) && infos.prev != null)
16221618
infos = infos.prev
16231619

1624-
if (validTo < curPeriod) {
1625-
assertCorrectThread()
1620+
if (_validTo < curPeriod) {
16261621
// adapt any infos that come from previous runs
1627-
val current = phase
1622+
val curPhase = outer.phase
16281623
try {
1629-
infos = adaptInfos(infos)
1624+
if (infos != null && outer.runId(infos.validFrom) != outer.currentRunId) {
1625+
// scala/bug#8871 Discard all but the first element of type history. Specialization only works in the resident
1626+
// compiler / REPL if re-run its info transformer in this run to correctly populate its
1627+
// per-run caches, e.g. typeEnv
1628+
infos = adaptInfo(infos.oldest)
1629+
}
16301630

16311631
//assert(runId(validTo) == currentRunId, name)
16321632
//assert(runId(infos.validFrom) == currentRunId, name)
16331633

1634-
if (validTo < curPeriod) {
1635-
var itr = nextFrom(phaseId(validTo))
1636-
infoTransformers = itr; // caching optimization
1637-
while (itr.pid != NoPhase.id && itr.pid < current.id) {
1638-
phase = phaseWithId(itr.pid)
1639-
val info1 = itr.transform(this, infos.info)
1640-
if (info1 ne infos.info) {
1641-
infos = TypeHistory(currentPeriod + 1, info1, infos)
1642-
this.infos = infos
1643-
}
1644-
_validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
1645-
itr = itr.next
1646-
}
1647-
_validTo = if (itr.pid == NoPhase.id) curPeriod
1648-
else period(currentRunId, itr.pid)
1634+
if (_validTo < curPeriod) {
1635+
infos = transformInfos(infos, curPhase, curPeriod)
16491636
}
16501637
} finally {
1651-
phase = current
1638+
outer.phase = curPhase
16521639
}
16531640
}
16541641
}
16551642
infos.info
16561643
}
16571644

1645+
private def transformInfos(infos0: TypeHistory, curPhase: Phase, curPeriod: Period): TypeHistory = {
1646+
assertCorrectThread()
1647+
var infos = infos0
1648+
var itr = nextFrom(phaseId(_validTo))
1649+
infoTransformers = itr; // caching optimization
1650+
while (itr.pid != NoPhase.id && itr.pid < curPhase.id) {
1651+
phase = phaseWithId(itr.pid)
1652+
val info1 = itr.transform(this, infos.info)
1653+
if (info1 ne infos.info) {
1654+
infos = TypeHistory(currentPeriod + 1, info1, infos)
1655+
this.infos = infos
1656+
}
1657+
_validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
1658+
itr = itr.next
1659+
}
1660+
_validTo = if (itr.pid == NoPhase.id) curPeriod
1661+
else period(currentRunId, itr.pid)
1662+
infos
1663+
}
1664+
16581665
// adapt to new run in fsc.
1659-
private def adaptInfos(infos: TypeHistory): TypeHistory = {
1666+
private def adaptInfo(oldest: TypeHistory): TypeHistory = {
16601667
assert(isCompilerUniverse)
1661-
if (infos == null || runId(infos.validFrom) == currentRunId) {
1662-
infos
1663-
} else if (infos ne infos.oldest) {
1664-
// scala/bug#8871 Discard all but the first element of type history. Specialization only works in the resident
1665-
// compiler / REPL if re-run its info transformer in this run to correctly populate its
1666-
// per-run caches, e.g. typeEnv
1667-
adaptInfos(infos.oldest)
1668+
assert(oldest.prev == null)
1669+
val pid = phaseId(oldest.validFrom)
1670+
1671+
_validTo = period(currentRunId, pid)
1672+
phase = phaseWithId(pid)
1673+
1674+
val info1 = adaptToNewRunMap(oldest.info)
1675+
if (info1 eq oldest.info) {
1676+
oldest.validFrom = validTo
1677+
this.infos = oldest
1678+
oldest
16681679
} else {
1669-
val prev1 = adaptInfos(infos.prev)
1670-
if (prev1 ne infos.prev) prev1
1671-
else {
1672-
val pid = phaseId(infos.validFrom)
1673-
1674-
_validTo = period(currentRunId, pid)
1675-
phase = phaseWithId(pid)
1676-
1677-
val info1 = adaptToNewRunMap(infos.info)
1678-
if (info1 eq infos.info) {
1679-
infos.validFrom = validTo
1680-
infos
1681-
} else {
1682-
this.infos = TypeHistory(validTo, info1, prev1)
1683-
this.infos
1684-
}
1685-
}
1680+
this.infos = TypeHistory(validTo, info1, null)
1681+
this.infos
16861682
}
16871683
}
16881684

1685+
16891686
/** Raises a `MissingRequirementError` if this symbol is a `StubSymbol` */
16901687
def failIfStub(): Unit = {}
16911688

0 commit comments

Comments
 (0)