summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-02-05 20:59:42 +0100
committerEugene Burmako <xeno.by@gmail.com>2013-02-11 19:18:29 +0100
commitf4dd56ca5d5adb2a9183991a7ecebc2b6a1f1fc5 (patch)
tree01c10742cbc292872d66ad4313b6eba3c5f077a2 /src/reflect
parentdd148de5a875dd8d691ffdd983b7f2b978a148df (diff)
downloadscala-f4dd56ca5d5adb2a9183991a7ecebc2b6a1f1fc5.tar.gz
scala-f4dd56ca5d5adb2a9183991a7ecebc2b6a1f1fc5.tar.bz2
scala-f4dd56ca5d5adb2a9183991a7ecebc2b6a1f1fc5.zip
synchronizes names
Previously we didn't have all possible name creation facilities covered with locks, so some of them silently misbehaved and caused much grief: http://groups.google.com/group/scala-internals/browse_thread/thread/ec1d3e2c4bcb000a. This patch gets all the name factories under control. Unfortunately it comes at a performance cost, which has to be evaluated.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala54
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedOps.scala8
2 files changed, 35 insertions, 27 deletions
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index c78ba72dfb..01ad18d3a0 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -21,7 +21,7 @@ trait LowPriorityNames {
* @author Martin Odersky
* @version 1.0, 05/02/2005
*/
-trait Names extends api.Names with LowPriorityNames {
+trait Names extends api.Names with LowPriorityNames { self =>
implicit def promoteTermNamesAsNecessary(name: Name): TermName = name.toTermName
// Operations -------------------------------------------------------------
@@ -109,6 +109,26 @@ trait Names extends api.Names with LowPriorityNames {
protected def newTypeName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TypeName =
newTermName(cs, offset, len, cachedString).toTypeName
+ protected def toTypeName(termName: TermName): TypeName = {
+ val h = hashValue(chrs, termName.index, termName.len) & HASH_MASK
+ var n = typeHashtable(h)
+ while ((n ne null) && n.start != termName.index)
+ n = n.next
+
+ if (n ne null) n
+ else termName.createCompanionName(h)
+ }
+
+ protected def toTermName(typeName: TypeName): TermName = {
+ val h = hashValue(chrs, typeName.index, typeName.len) & HASH_MASK
+ var n = termHashtable(h)
+ while ((n ne null) && n.start != typeName.index)
+ n = n.next
+
+ if (n ne null) n
+ else typeName.createCompanionName(h)
+ }
+
/** Create a term name from string. */
def newTermName(s: String): TermName = newTermName(s.toCharArray(), 0, s.length(), null)
@@ -145,7 +165,7 @@ trait Names extends api.Names with LowPriorityNames {
* or Strings as Names. Give names the key functions the absence of which
* make people want Strings all the time.
*/
- sealed abstract class Name(protected val index: Int, protected val len: Int) extends NameApi {
+ sealed abstract class Name(protected[Names] val index: Int, protected[Names] val len: Int) extends NameApi {
type ThisNameType >: Null <: Name
protected[this] def thisName: ThisNameType
@@ -463,21 +483,21 @@ trait Names extends api.Names with LowPriorityNames {
* TermName_R and TypeName_R recreate it each time toString is called.
*/
private class TermName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TermName(index0, len0, hash) {
- protected def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString)
+ @inline final def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString)
override def newName(str: String): TermName = newTermNameCached(str)
}
private class TypeName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TypeName(index0, len0, hash) {
- protected def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString)
+ @inline final def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString)
override def newName(str: String): TypeName = newTypeNameCached(str)
}
private class TermName_R(index0: Int, len0: Int, hash: Int) extends TermName(index0, len0, hash) {
- protected def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h)
+ @inline final def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h)
override def toString = new String(chrs, index, len)
}
private class TypeName_R(index0: Int, len0: Int, hash: Int) extends TypeName(index0, len0, hash) {
- protected def createCompanionName(h: Int): TermName = new TermName_R(index, len, h)
+ @inline final def createCompanionName(h: Int): TermName = new TermName_R(index, len, h)
override def toString = new String(chrs, index, len)
}
@@ -490,22 +510,14 @@ trait Names extends api.Names with LowPriorityNames {
def isTermName: Boolean = true
def isTypeName: Boolean = false
def toTermName: TermName = this
- def toTypeName: TypeName = {
- val h = hashValue(chrs, index, len) & HASH_MASK
- var n = typeHashtable(h)
- while ((n ne null) && n.start != index)
- n = n.next
-
- if (n ne null) n
- else createCompanionName(h)
- }
+ def toTypeName: TypeName = self.toTypeName(this)
def newName(str: String): TermName = newTermName(str)
def companionName: TypeName = toTypeName
def subName(from: Int, to: Int): TermName =
newTermName(chrs, start + from, to - from)
def nameKind = "term"
- protected def createCompanionName(h: Int): TypeName
+ def createCompanionName(h: Int): TypeName
}
implicit val TermNameTag = ClassTag[TermName](classOf[TermName])
@@ -518,15 +530,7 @@ trait Names extends api.Names with LowPriorityNames {
typeHashtable(hash) = this
def isTermName: Boolean = false
def isTypeName: Boolean = true
- def toTermName: TermName = {
- val h = hashValue(chrs, index, len) & HASH_MASK
- var n = termHashtable(h)
- while ((n ne null) && n.start != index)
- n = n.next
-
- if (n ne null) n
- else createCompanionName(h)
- }
+ def toTermName: TermName = self.toTermName(this)
def toTypeName: TypeName = this
def newName(str: String): TypeName = newTypeName(str)
def companionName: TermName = toTermName
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
index d022bf66ba..f9f4a26b42 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
@@ -13,8 +13,12 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable
// therefore we don't have a danger of a deadlock from having a fine-grained lock for name creation
private lazy val nameLock = new Object
- override def newTermName(s: String): TermName = nameLock.synchronized { super.newTermName(s) }
- override def newTypeName(s: String): TypeName = nameLock.synchronized { super.newTypeName(s) }
+ // these three methods are the only gateways into name hashtable manipulations
+ // we need to protected them with a lock, because they are by far not atomic
+ override protected def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName =
+ nameLock.synchronized { super.newTermName(cs, offset, len, cachedString) }
+ override protected def toTypeName(termName: TermName): TypeName = nameLock.synchronized { super.toTypeName(termName) }
+ override protected def toTermName(typeName: TypeName): TermName = nameLock.synchronized { super.toTermName(typeName) }
// BaseTypeSeqs