Skip to content

Commit 055a02e

Browse files
committed
Optimise ClassTag lookup
- Optimize ClassTag.apply to avoid testing for primitive classes one-by-one. - Share instance of ClassTag in a ClassValue based cache and rely on this in the compiler where we had previously hoisted hot instances.
1 parent 12ae196 commit 055a02e

File tree

1 file changed

+25
-16
lines changed

1 file changed

+25
-16
lines changed

library/src/scala/reflect/ClassTag.scala

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,29 +121,38 @@ object ClassTag {
121121
val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing
122122
val Null : ClassTag[scala.Null] = Manifest.Null
123123

124+
private[this] val cache = new ClassValue[ClassTag[_]] {
125+
override def computeValue(runtimeClass: jClass[_]): ClassTag[_] = {
126+
runtimeClass match {
127+
case x if x.isPrimitive => primitiveClassTag(runtimeClass)
128+
case ObjectTYPE => ClassTag.Object
129+
case NothingTYPE => ClassTag.Nothing
130+
case NullTYPE => ClassTag.Null
131+
case _ => new GenericClassTag[AnyRef](runtimeClass)
132+
}
133+
}
134+
135+
private def primitiveClassTag[T](runtimeClass: Class[_]): ClassTag[_] = runtimeClass match {
136+
case java.lang.Byte.TYPE => ClassTag.Byte
137+
case java.lang.Short.TYPE => ClassTag.Short
138+
case java.lang.Character.TYPE => ClassTag.Char
139+
case java.lang.Integer.TYPE => ClassTag.Int
140+
case java.lang.Long.TYPE => ClassTag.Long
141+
case java.lang.Float.TYPE => ClassTag.Float
142+
case java.lang.Double.TYPE => ClassTag.Double
143+
case java.lang.Boolean.TYPE => ClassTag.Boolean
144+
case java.lang.Void.TYPE => ClassTag.Unit
145+
}
146+
}
147+
124148
@SerialVersionUID(1L)
125149
private class GenericClassTag[T](val runtimeClass: jClass[_]) extends ClassTag[T] {
126150
override def newArray(len: Int): Array[T] = {
127151
java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
128152
}
129153
}
130154

131-
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] =
132-
runtimeClass1 match {
133-
case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
134-
case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
135-
case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
136-
case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
137-
case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
138-
case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
139-
case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
140-
case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
141-
case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
142-
case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
143-
case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
144-
case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]]
145-
case _ => new GenericClassTag[T](runtimeClass1)
146-
}
155+
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = cache.get(runtimeClass1).asInstanceOf[ClassTag[T]]
147156

148157
def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass)
149158
}

0 commit comments

Comments
 (0)