@@ -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