Skip to content

Commit 3ca0419

Browse files
committed
Break names out of the cake
Allow names to be shared adapted from retronym#43 adapted from
1 parent 2ed9ba0 commit 3ca0419

File tree

5 files changed

+150
-82
lines changed

5 files changed

+150
-82
lines changed

src/compiler/scala/tools/nsc/Global.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import scala.tools.nsc.classpath._
4141
import scala.tools.nsc.profile.Profiler
4242
import scala.util.control.NonFatal
4343
import java.io.Closeable
44+
import java.util.concurrent.atomic.AtomicReference
45+
4446
import scala.annotation.tailrec
4547

4648
class Global(var currentSettings: Settings, reporter0: LegacyReporter)
@@ -1731,6 +1733,17 @@ class Global(var currentSettings: Settings, reporter0: LegacyReporter)
17311733
perRunCaches.clearAll()
17321734
closeableRegistry.close()
17331735
}
1736+
override protected def newNameTable: NameTable = {
1737+
if (currentSettings.YcacheNameTable) {
1738+
var shared: NameTable = null
1739+
do {
1740+
shared = Global.nameTableCache.get
1741+
if (shared == null) Global.nameTableCache.compareAndSet(null, new scala.reflect.internal.NameTable)
1742+
} while (shared == null)
1743+
shared
1744+
}
1745+
else super.newNameTable
1746+
}
17341747
}
17351748

17361749
object Global {
@@ -1743,4 +1756,5 @@ object Global {
17431756
override def keepsTypeParams = false
17441757
def run(): Unit = { throw new Error("InitPhase.run") }
17451758
}
1759+
private val nameTableCache = new AtomicReference[scala.reflect.internal.NameTable]
17461760
}

src/compiler/scala/tools/nsc/settings/ScalaSettings.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ trait ScalaSettings extends AbsScalaSettings
251251
val YcachePluginClassLoader = CachePolicy.setting("plugin", "compiler plugins")
252252
val YcacheMacroClassLoader = CachePolicy.setting("macro", "macros")
253253
val YmacroClasspath = PathSetting ("-Ymacro-classpath", "The classpath used to reflectively load macro implementations, default is the compilation classpath.", "")
254+
val YcacheNameTable = BooleanSetting ("-Ycache-name-table", "Share a single name table for concurrently running instances of the compiler")
254255

255256
val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
256257
val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method")

src/reflect/scala/reflect/api/Names.scala

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,82 @@ trait Names {
5555
// @deprecated("use explicit `TypeName(s)` instead", "2.11.0")
5656
// implicit def stringToTypeName(s: String): TypeName = TypeName(s)
5757

58+
type NameTable <: NameTableApi
59+
60+
val nameTable: NameTable
61+
5862
/** The abstract type of names.
5963
* @group Names
6064
*/
61-
type Name >: Null <: AnyRef with NameApi
65+
type Name >: Null <: AnyRef with nameTable.NameApi
6266

6367
/** The abstract type of names representing terms.
6468
* @group Names
6569
*/
66-
type TypeName >: Null <: TypeNameApi with Name
70+
type TypeName >: Null <: nameTable.TypeNameApi with Name
71+
/** The abstract type of names representing types.
72+
* @group Names
73+
*/
74+
type TermName >: Null <: nameTable.TermNameApi with Name
75+
76+
/** The API of Name instances.
77+
* @group API
78+
*/
79+
type NameApi <: nameTable.NameApi
80+
81+
/** Create a new term name.
82+
* @group Names
83+
*/
84+
@deprecated("use TermName instead", "2.11.0")
85+
def newTermName(s: String): TermName
86+
87+
/** Creates a new type name.
88+
* @group Names
89+
*/
90+
@deprecated("use TypeName instead", "2.11.0")
91+
def newTypeName(s: String): TypeName
92+
93+
/** The constructor/extractor for `TermName` instances.
94+
* @group Extractors
95+
*/
96+
val TermName: TermNameExtractor
97+
98+
/** An extractor class to create and pattern match with syntax `TermName(s)`.
99+
* @group Extractors
100+
*/
101+
abstract class TermNameExtractor {
102+
def apply(s: String): TermName
103+
def unapply(name: TermName): Option[String]
104+
}
105+
106+
/** The constructor/extractor for `TypeName` instances.
107+
* @group Extractors
108+
*/
109+
val TypeName: TypeNameExtractor
110+
111+
/** An extractor class to create and pattern match with syntax `TypeName(s)`.
112+
* @group Extractors
113+
*/
114+
abstract class TypeNameExtractor {
115+
def apply(s: String): TypeName
116+
def unapply(name: TypeName): Option[String]
117+
}
118+
}
119+
120+
abstract class NameTableApi {
121+
/** The abstract type of names.
122+
* @group Names
123+
*/
124+
type Name >: Null <: AnyRef with NameApi
125+
126+
type TypeName >: Null <: TypeNameApi with Name
67127

68-
/** Has no special methods. Is here to provides erased identity for `TypeName`.
69-
* @group API
70-
*/
71-
trait TypeNameApi
72128

73129
/** The abstract type of names representing types.
74130
* @group Names
75131
*/
76132
type TermName >: Null <: TermNameApi with Name
77133

78-
/** Has no special methods. Is here to provides erased identity for `TermName`.
79-
* @group API
80-
*/
81-
trait TermNameApi
82134

83135
/** The API of Name instances.
84136
* @group API
@@ -116,6 +168,15 @@ trait Names {
116168
*/
117169
def encodedName: Name
118170
}
171+
/** Has no special methods. Is here to provides erased identity for `TypeName`.
172+
* @group API
173+
*/
174+
trait TypeNameApi extends NameApi
175+
/** Has no special methods. Is here to provides erased identity for `TermName`.
176+
* @group API
177+
*/
178+
trait TermNameApi extends NameApi
179+
119180

120181
/** Create a new term name.
121182
* @group Names
@@ -129,29 +190,4 @@ trait Names {
129190
@deprecated("use TypeName instead", "2.11.0")
130191
def newTypeName(s: String): TypeName
131192

132-
/** The constructor/extractor for `TermName` instances.
133-
* @group Extractors
134-
*/
135-
val TermName: TermNameExtractor
136-
137-
/** An extractor class to create and pattern match with syntax `TermName(s)`.
138-
* @group Extractors
139-
*/
140-
abstract class TermNameExtractor {
141-
def apply(s: String): TermName
142-
def unapply(name: TermName): Option[String]
143-
}
144-
145-
/** The constructor/extractor for `TypeName` instances.
146-
* @group Extractors
147-
*/
148-
val TypeName: TypeNameExtractor
149-
150-
/** An extractor class to create and pattern match with syntax `TypeName(s)`.
151-
* @group Extractors
152-
*/
153-
abstract class TypeNameExtractor {
154-
def apply(s: String): TypeName
155-
def unapply(name: TypeName): Option[String]
156-
}
157193
}

src/reflect/scala/reflect/internal/Names.scala

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,51 @@ package internal
1616

1717
import java.util.concurrent.ConcurrentHashMap
1818

19+
import scala.reflect.api.NameTableApi
20+
1921
trait Names extends api.Names {
20-
def nameTableSize: Int = cache.size
22+
type NameTable = scala.reflect.internal.NameTable
23+
override val nameTable: NameTable = newNameTable
2124

22-
override final type Name = AName
23-
override final type TypeName = TermNameImpl#TypeNameImpl
24-
override final type TermName = TermNameImpl
25+
protected def newNameTable: NameTable = new NameTable
26+
27+
def nameTableSize: Int = nameTable.nameTableSize
28+
override final type Name = nameTable.AName
29+
override final type TypeName = nameTable.TypeNameImpl
30+
override final type TermName = nameTable.TermNameImpl
2531

2632
implicit final val NameTag = ClassTag[Name](classOf[Name])
2733
implicit final val TermNameTag = ClassTag[TermName](classOf[TermName])
2834
implicit final val TypeNameTag = ClassTag[TypeName](classOf[TypeName])
2935

30-
31-
override object TermName extends TermNameExtractor {
32-
@inline override def apply(s: String): TermName = newTermName(s)
33-
override def unapply(name: TermName): Option[String] = Some(name.rawString)
36+
override final def newTypeName(value: String): TypeName = nameTable.newTypeName(value)
37+
override final def newTermName(value: String): TermName = nameTable.newTermName(value)
38+
object TermName extends TermNameExtractor {
39+
def apply(s: String) = newTermName(s)
40+
def unapply(name: TermName): Option[String] = Some(name.toString)
3441
}
35-
override object TypeName extends TypeNameExtractor {
36-
@inline override def apply(s: String): TypeName = newTypeName(s)
37-
override def unapply(name: TypeName): Option[String] = Some(name.rawString)
42+
object TypeName extends TypeNameExtractor {
43+
def apply(s: String) = newTypeName(s)
44+
def unapply(name: TypeName): Option[String] = Some(name.toString)
3845
}
39-
override final def newTypeName(value: String): TypeName = newTermName(value).companionName
46+
//deprecated stuff
47+
@deprecated
48+
@inline final def newTermNameCached(s: String): TermName = newTermName(s)
49+
50+
@deprecated
51+
@inline final def newTypeNameCached(s: String): TypeName = newTypeName(s)
52+
}
53+
class NameTable extends NameTableApi {
54+
override final type Name = AName
55+
override final type TypeName = TypeNameImpl
56+
override final type TermName = TermNameImpl
57+
58+
def nameTableSize: Int = cache.size
59+
60+
private[this] final val cache = new ConcurrentHashMap[String, TermNameImpl](1000, 0.75F, 1)
4061

41-
override final def newTermName(value: String): TermName = {
42-
//TODO consider a better structure to use than a CHM
62+
override final def newTermName(value: String): TermNameImpl = {
63+
//TODO consider a better structure to use than a CHM
4364
var res = cache.get(value)
4465
if (res eq null) {
4566
val next = new TermNameImpl(value)
@@ -50,25 +71,22 @@ trait Names extends api.Names {
5071
res
5172
//same as cache.computeIfAbsent(value, new NameHolder(_)) but faster
5273
}
53-
private[this] final val cache = new ConcurrentHashMap[String, TermName](1000, 0.75F, 1)
54-
//deprecated stuff
55-
@deprecated @inline final def newTermNameCached(s: String): TermName = newTermName(s)
56-
@deprecated @inline final def newTypeNameCached(s: String): TypeName = newTypeName(s)
74+
final def newTypeName(value:String): TypeName = newTermName(value).companionName
5775

5876
abstract sealed class AName extends NameApi with CharSequence {
5977
type ThisNameType <: AName
6078
@inline override final def length(): Int = value.length
6179
override final def subSequence(start: Int, end: Int): CharSequence = value.subSequence(start, end)
6280
override def decoded: String = decodedName.toString
6381
override def encoded: String = encodedName.toString
64-
@inline private[Names] def rawString = value
65-
override def decodedName: ThisNameType
66-
override def encodedName: ThisNameType
82+
@inline private[NameTable] def rawString = value
83+
def decodedName: ThisNameType
84+
def encodedName: ThisNameType
6785

6886
//non API methods
6987
protected def value: String
7088

71-
def companionName: Name
89+
def companionName: AName
7290

7391
/** Return the subname with characters from from to to-1. */
7492
def subName(from: Int, to: Int): ThisNameType =
@@ -250,12 +268,12 @@ trait Names extends api.Names {
250268
}
251269
final class TermNameImpl(override val toString: String) extends AName with TermNameApi {
252270
type ThisNameType = TermName
271+
253272
override def isTermName = true
254273
override def isTypeName = false
255274

256275
override protected def value: String = toString
257276

258-
259277
override def toTermName: TermName = this
260278
override def toTypeName: TypeName = typeName
261279

@@ -269,7 +287,7 @@ trait Names extends api.Names {
269287
def identifier = identifier_ & 0x80FF
270288
def markAsIdentifier(java: Boolean, newIdentifier: Int) {
271289
require((identifier.toShort & 0x80FF) == identifier.toShort)
272-
val flag = (if (java) 0x1000 else 0x2000).toShort
290+
val flag = (if (java) 0x1000 else 0x2000).toShort
273291
if (identifier_ == 0) {
274292
//first call
275293
this.identifier_ = (newIdentifier | flag).toShort
@@ -290,31 +308,30 @@ trait Names extends api.Names {
290308
else this
291309
}
292310
override lazy final val encodedName: TermName = {
293-
val res = NameTransformer.encode(value)
294-
if (res == value) this else newName(res)
295-
}
296-
297-
private lazy val typeName:TypeName = new TypeNameImpl
311+
val res = NameTransformer.encode(value)
312+
if (res == value) this else newName(res)
313+
}
298314

315+
private[NameTable] lazy val typeName: TypeNameImpl = new TypeNameImpl(this)
299316

300-
final class TypeNameImpl extends AName with TypeNameApi {
301-
type ThisNameType = TypeName
302-
override def isTermName = false
303-
override def isTypeName = true
304-
override def decodedName: TypeName = TermNameImpl.this.decodedName.typeName
305-
override def encodedName: TypeName = TermNameImpl.this.encodedName.typeName
317+
}
318+
final class TypeNameImpl(term: TermNameImpl) extends AName with TypeNameApi {
319+
type ThisNameType = TypeName
320+
override def isTermName = false
321+
override def isTypeName = true
322+
override def decodedName: TypeName = term.decodedName.typeName
323+
override def encodedName: TypeName = term.encodedName.typeName
306324

307325

308-
override protected def value: String = TermNameImpl.this.toString
309-
override def toString: String = TermNameImpl.this.toString
326+
override protected def value: String = term.toString
327+
override def toString: String = term.toString
310328

311-
override def toTermName: TermName = TermNameImpl.this
312-
override def toTypeName: TypeName = this
329+
override def toTermName: TermName = term
330+
override def toTypeName: TypeName = this
313331

314-
override def companionName = TermNameImpl.this
315-
override def newName(str: String) = newTypeName(str)
316-
override def nameKind = "type"
317-
def debugString = decoded + "!"
318-
}
332+
override def companionName = term
333+
override def newName(str: String) = newTypeName(str)
334+
override def nameKind = "type"
335+
def debugString = decoded + "!"
319336
}
320337
}

test/files/run/reflection-names.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
(java.lang.String,bc)
2-
(scala.reflect.internal.Names$TermName_R,bc)
3-
(scala.reflect.internal.Names$TypeName_R,bc)
4-
(scala.reflect.internal.Names$TypeName_R,bc)
2+
(scala.reflect.internal.NameTable$TermNameImpl,bc)
3+
(scala.reflect.internal.NameTable$TypeNameImpl,bc)
4+
(scala.reflect.internal.NameTable$TypeNameImpl,bc)

0 commit comments

Comments
 (0)