Skip to content

Commit

Permalink
breaking Names from th cake
Browse files Browse the repository at this point in the history
Allow names to be shared between compilations

adapted from retronym#43
  • Loading branch information
mkeskells committed Apr 25, 2019
1 parent 2ed9ba0 commit 54731e6
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 82 deletions.
14 changes: 14 additions & 0 deletions src/compiler/scala/tools/nsc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import scala.tools.nsc.classpath._
import scala.tools.nsc.profile.Profiler
import scala.util.control.NonFatal
import java.io.Closeable
import java.util.concurrent.atomic.AtomicReference

import scala.annotation.tailrec

class Global(var currentSettings: Settings, reporter0: LegacyReporter)
Expand Down Expand Up @@ -1731,6 +1733,17 @@ class Global(var currentSettings: Settings, reporter0: LegacyReporter)
perRunCaches.clearAll()
closeableRegistry.close()
}
override protected def newNameTable: NameTable = {
if (currentSettings.YcacheNameTable) {
var shared: NameTable = null
do {
shared = Global.nameTableCache.get
if (shared == null) Global.nameTableCache.compareAndSet(null, new scala.reflect.internal.NameTable)
} while (shared == null)
shared
}
else super.newNameTable
}
}

object Global {
Expand All @@ -1743,4 +1756,5 @@ object Global {
override def keepsTypeParams = false
def run(): Unit = { throw new Error("InitPhase.run") }
}
private val nameTableCache = new AtomicReference[scala.reflect.internal.NameTable]
}
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ trait ScalaSettings extends AbsScalaSettings
val YcachePluginClassLoader = CachePolicy.setting("plugin", "compiler plugins")
val YcacheMacroClassLoader = CachePolicy.setting("macro", "macros")
val YmacroClasspath = PathSetting ("-Ymacro-classpath", "The classpath used to reflectively load macro implementations, default is the compilation classpath.", "")
val YcacheNameTable = BooleanSetting ("-Ycache-name-table", "Share a single name table for concurrently running instances of the compiler")

val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method")
Expand Down
106 changes: 71 additions & 35 deletions src/reflect/scala/reflect/api/Names.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,82 @@ trait Names {
// @deprecated("use explicit `TypeName(s)` instead", "2.11.0")
// implicit def stringToTypeName(s: String): TypeName = TypeName(s)

type NameTable <: NameTableApi

val nameTable: NameTable

/** The abstract type of names.
* @group Names
*/
type Name >: Null <: AnyRef with NameApi
type Name >: Null <: AnyRef with nameTable.NameApi

/** The abstract type of names representing terms.
* @group Names
*/
type TypeName >: Null <: TypeNameApi with Name
type TypeName >: Null <: nameTable.TypeNameApi with Name
/** The abstract type of names representing types.
* @group Names
*/
type TermName >: Null <: nameTable.TermNameApi with Name

/** The API of Name instances.
* @group API
*/
type NameApi <: nameTable.NameApi

/** Create a new term name.
* @group Names
*/
@deprecated("use TermName instead", "2.11.0")
def newTermName(s: String): TermName

/** Creates a new type name.
* @group Names
*/
@deprecated("use TypeName instead", "2.11.0")
def newTypeName(s: String): TypeName

/** The constructor/extractor for `TermName` instances.
* @group Extractors
*/
val TermName: TermNameExtractor

/** An extractor class to create and pattern match with syntax `TermName(s)`.
* @group Extractors
*/
abstract class TermNameExtractor {
def apply(s: String): TermName
def unapply(name: TermName): Option[String]
}

/** The constructor/extractor for `TypeName` instances.
* @group Extractors
*/
val TypeName: TypeNameExtractor

/** An extractor class to create and pattern match with syntax `TypeName(s)`.
* @group Extractors
*/
abstract class TypeNameExtractor {
def apply(s: String): TypeName
def unapply(name: TypeName): Option[String]
}
}

abstract class NameTableApi {
/** The abstract type of names.
* @group Names
*/
type Name >: Null <: AnyRef with NameApi

type TypeName >: Null <: TypeNameApi with Name

/** Has no special methods. Is here to provides erased identity for `TypeName`.
* @group API
*/
trait TypeNameApi

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

/** Has no special methods. Is here to provides erased identity for `TermName`.
* @group API
*/
trait TermNameApi

/** The API of Name instances.
* @group API
Expand Down Expand Up @@ -116,6 +168,15 @@ trait Names {
*/
def encodedName: Name
}
/** Has no special methods. Is here to provides erased identity for `TypeName`.
* @group API
*/
trait TypeNameApi extends NameApi
/** Has no special methods. Is here to provides erased identity for `TermName`.
* @group API
*/
trait TermNameApi extends NameApi


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

/** The constructor/extractor for `TermName` instances.
* @group Extractors
*/
val TermName: TermNameExtractor

/** An extractor class to create and pattern match with syntax `TermName(s)`.
* @group Extractors
*/
abstract class TermNameExtractor {
def apply(s: String): TermName
def unapply(name: TermName): Option[String]
}

/** The constructor/extractor for `TypeName` instances.
* @group Extractors
*/
val TypeName: TypeNameExtractor

/** An extractor class to create and pattern match with syntax `TypeName(s)`.
* @group Extractors
*/
abstract class TypeNameExtractor {
def apply(s: String): TypeName
def unapply(name: TypeName): Option[String]
}
}
105 changes: 61 additions & 44 deletions src/reflect/scala/reflect/internal/Names.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,51 @@ package internal

import java.util.concurrent.ConcurrentHashMap

import scala.reflect.api.NameTableApi

trait Names extends api.Names {
def nameTableSize: Int = cache.size
type NameTable = scala.reflect.internal.NameTable
override val nameTable: NameTable = newNameTable

override final type Name = AName
override final type TypeName = TermNameImpl#TypeNameImpl
override final type TermName = TermNameImpl
protected def newNameTable: NameTable = new NameTable

def nameTableSize: Int = nameTable.nameTableSize
override final type Name = nameTable.AName
override final type TypeName = nameTable.TypeNameImpl
override final type TermName = nameTable.TermNameImpl

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


override object TermName extends TermNameExtractor {
@inline override def apply(s: String): TermName = newTermName(s)
override def unapply(name: TermName): Option[String] = Some(name.rawString)
override final def newTypeName(value: String): TypeName = nameTable.newTypeName(value)
override final def newTermName(value: String): TermName = nameTable.newTermName(value)
object TermName extends TermNameExtractor {
def apply(s: String) = newTermName(s)
def unapply(name: TermName): Option[String] = Some(name.toString)
}
override object TypeName extends TypeNameExtractor {
@inline override def apply(s: String): TypeName = newTypeName(s)
override def unapply(name: TypeName): Option[String] = Some(name.rawString)
object TypeName extends TypeNameExtractor {
def apply(s: String) = newTypeName(s)
def unapply(name: TypeName): Option[String] = Some(name.toString)
}
override final def newTypeName(value: String): TypeName = newTermName(value).companionName
//deprecated stuff
@deprecated
@inline final def newTermNameCached(s: String): TermName = newTermName(s)

@deprecated
@inline final def newTypeNameCached(s: String): TypeName = newTypeName(s)
}
class NameTable extends NameTableApi {
override final type Name = AName
override final type TypeName = TypeNameImpl
override final type TermName = TermNameImpl

def nameTableSize: Int = cache.size

private[this] final val cache = new ConcurrentHashMap[String, TermNameImpl](1000, 0.75F, 1)

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

abstract sealed class AName extends NameApi with CharSequence {
type ThisNameType <: AName
@inline override final def length(): Int = value.length
override final def subSequence(start: Int, end: Int): CharSequence = value.subSequence(start, end)
override def decoded: String = decodedName.toString
override def encoded: String = encodedName.toString
@inline private[Names] def rawString = value
override def decodedName: ThisNameType
override def encodedName: ThisNameType
@inline private[NameTable] def rawString = value
def decodedName: ThisNameType
def encodedName: ThisNameType

//non API methods
protected def value: String

def companionName: Name
def companionName: AName

/** Return the subname with characters from from to to-1. */
def subName(from: Int, to: Int): ThisNameType =
Expand Down Expand Up @@ -250,12 +268,12 @@ trait Names extends api.Names {
}
final class TermNameImpl(override val toString: String) extends AName with TermNameApi {
type ThisNameType = TermName

override def isTermName = true
override def isTypeName = false

override protected def value: String = toString


override def toTermName: TermName = this
override def toTypeName: TypeName = typeName

Expand All @@ -269,7 +287,7 @@ trait Names extends api.Names {
def identifier = identifier_ & 0x80FF
def markAsIdentifier(java: Boolean, newIdentifier: Int) {
require((identifier.toShort & 0x80FF) == identifier.toShort)
val flag = (if (java) 0x1000 else 0x2000).toShort
val flag = (if (java) 0x1000 else 0x2000).toShort
if (identifier_ == 0) {
//first call
this.identifier_ = (newIdentifier | flag).toShort
Expand All @@ -290,31 +308,30 @@ trait Names extends api.Names {
else this
}
override lazy final val encodedName: TermName = {
val res = NameTransformer.encode(value)
if (res == value) this else newName(res)
}

private lazy val typeName:TypeName = new TypeNameImpl
val res = NameTransformer.encode(value)
if (res == value) this else newName(res)
}

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

final class TypeNameImpl extends AName with TypeNameApi {
type ThisNameType = TypeName
override def isTermName = false
override def isTypeName = true
override def decodedName: TypeName = TermNameImpl.this.decodedName.typeName
override def encodedName: TypeName = TermNameImpl.this.encodedName.typeName
}
final class TypeNameImpl(term: TermNameImpl) extends AName with TypeNameApi {
type ThisNameType = TypeName
override def isTermName = false
override def isTypeName = true
override def decodedName: TypeName = term.decodedName.typeName
override def encodedName: TypeName = term.encodedName.typeName


override protected def value: String = TermNameImpl.this.toString
override def toString: String = TermNameImpl.this.toString
override protected def value: String = term.toString
override def toString: String = term.toString

override def toTermName: TermName = TermNameImpl.this
override def toTypeName: TypeName = this
override def toTermName: TermName = term
override def toTypeName: TypeName = this

override def companionName = TermNameImpl.this
override def newName(str: String) = newTypeName(str)
override def nameKind = "type"
def debugString = decoded + "!"
}
override def companionName = term
override def newName(str: String) = newTypeName(str)
override def nameKind = "type"
def debugString = decoded + "!"
}
}
2 changes: 0 additions & 2 deletions src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
this.NoSymbol
this.CyclicReference
this.SymbolOps
this.TermName
this.TypeName
this.Liftable
this.Unliftable
this.BooleanFlag
Expand Down
3 changes: 2 additions & 1 deletion src/reflect/scala/reflect/runtime/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ package runtime {
private[scala] object Macros {
def currentMirror(c: scala.reflect.macros.blackbox.Context): c.Expr[universe.Mirror] = {
import c.universe._
val x: c.universe.TermName = TermName.apply("scala")
val runtimeClass = c.reifyEnclosingRuntimeClass
if (runtimeClass.isEmpty) c.abort(c.enclosingPosition, "call site does not have an enclosing class")
val scalaPackage = Select(Ident(TermName("_root_")), TermName("scala"))
val scalaPackage = Select(Ident(TermName.apply("_root_")), TermName.apply("scala"))
val runtimeUniverse = Select(Select(Select(scalaPackage, TermName("reflect")), TermName("runtime")), TermName("universe"))
val currentMirror = Apply(Select(runtimeUniverse, TermName("runtimeMirror")), List(Select(runtimeClass, TermName("getClassLoader"))))
c.Expr[Nothing](currentMirror)(c.WeakTypeTag.Nothing)
Expand Down

0 comments on commit 54731e6

Please sign in to comment.