diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-01-04 11:58:53 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-01-04 11:58:53 -0800 |
commit | 78693e0a1c7d672877e1d689eacad834667aa306 (patch) | |
tree | 682d345618a783d544843438425bf29ff530ce2a /src | |
parent | 9dc2e23f6afc8700d973d5cfc8f4bdd9e415f7b2 (diff) | |
parent | 45ef0514e97ff618ce1d68f9c81b5024fa793af1 (diff) | |
download | scala-78693e0a1c7d672877e1d689eacad834667aa306.tar.gz scala-78693e0a1c7d672877e1d689eacad834667aa306.tar.bz2 scala-78693e0a1c7d672877e1d689eacad834667aa306.zip |
Merge pull request #1821 from scalamacros/ticket/6638
bind + argc specialization = 20x perf boost
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/collection/mutable/WrappedArray.scala | 2 | ||||
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 5 | ||||
-rw-r--r-- | src/reflect/scala/reflect/api/Mirrors.scala | 10 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/JavaMirrors.scala | 50 |
4 files changed, 64 insertions, 3 deletions
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index f02f5a241f..b83724090c 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -62,7 +62,7 @@ extends AbstractSeq[T] override def par = ParArray.handoff(array) private def elementClass: Class[_] = - arrayElementClass(repr.getClass) + arrayElementClass(array.getClass) override def toArray[U >: T : ClassTag]: Array[U] = { val thatElementClass = arrayElementClass(implicitly[ClassTag[U]]) diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index eddfe63118..f62d0ecd16 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -162,11 +162,13 @@ object ManifestFactory { private val NullTYPE = classOf[scala.runtime.Null$] val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any](ObjectTYPE, "Any") { + override def newArray(len: Int) = new Array[scala.Any](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) private def readResolve(): Any = Manifest.Any } val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { + override def newArray(len: Int) = new Array[java.lang.Object](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.Object } @@ -174,17 +176,20 @@ object ManifestFactory { val AnyRef: Manifest[scala.AnyRef] = Object.asInstanceOf[Manifest[scala.AnyRef]] val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { + override def newArray(len: Int) = new Array[scala.AnyVal](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.AnyVal } val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null](NullTYPE, "Null") { + override def newArray(len: Int) = new Array[scala.Null](len) override def <:<(that: ClassManifest[_]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) private def readResolve(): Any = Manifest.Null } val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { + override def newArray(len: Int) = new Array[scala.Nothing](len) override def <:<(that: ClassManifest[_]): Boolean = (that ne null) private def readResolve(): Any = Manifest.Nothing } diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index d0d8a37584..d30563c706 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -352,6 +352,11 @@ trait Mirrors { self: Universe => * the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor. */ def set(value: Any): Unit + + /** Creates a new mirror which uses the same symbol, but is bound to a different receiver. + * This is significantly faster than recreating the mirror from scratch. + */ + def bind(newReceiver: Any): FieldMirror } /** A mirror that reflects a method. @@ -373,6 +378,11 @@ trait Mirrors { self: Universe => * with invoking the corresponding method or constructor. */ def apply(args: Any*): Any + + /** Creates a new mirror which uses the same symbol, but is bound to a different receiver. + * This is significantly faster than recreating the mirror from scratch. + */ + def bind(newReceiver: Any): MethodMirror } /** A mirror that reflects the instance or static parts of a runtime class. diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 57cfb8b515..67b24cbdea 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -282,6 +282,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni if (!symbol.isMutable) ErrorSetImmutableField(symbol) jfield.set(receiver, value) } + def bind(newReceiver: Any) = new JavaFieldMirror(newReceiver, symbol) override def toString = s"field mirror for ${symbol.fullName} (bound to $receiver)" } @@ -329,7 +330,16 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni private def mkJavaMethodMirror[T: ClassTag](receiver: T, symbol: MethodSymbol): JavaMethodMirror = { if (isBytecodelessMethod(symbol)) new JavaBytecodelessMethodMirror(receiver, symbol) else if (symbol.paramss.flatten exists (p => isByNameParamType(p.info))) new JavaByNameMethodMirror(receiver, symbol) - else new JavaVanillaMethodMirror(receiver, symbol) + else { + symbol.paramss.flatten.length match { + case 0 => new JavaVanillaMethodMirror0(receiver, symbol) + case 1 => new JavaVanillaMethodMirror1(receiver, symbol) + case 2 => new JavaVanillaMethodMirror2(receiver, symbol) + case 3 => new JavaVanillaMethodMirror3(receiver, symbol) + case 4 => new JavaVanillaMethodMirror4(receiver, symbol) + case _ => new JavaVanillaMethodMirror(receiver, symbol) + } + } } private abstract class JavaMethodMirror(val symbol: MethodSymbol) @@ -340,8 +350,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni jmeth } + def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) + def jinvoke(jmeth: jMethod, receiver: Any, args: Seq[Any]): Any = { - val result = jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) + val result = jinvokeraw(jmeth, receiver, args) if (jmeth.getReturnType == java.lang.Void.TYPE) () else result } @@ -351,11 +363,43 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni private class JavaVanillaMethodMirror(val receiver: Any, symbol: MethodSymbol) extends JavaMethodMirror(symbol) { + def bind(newReceiver: Any) = new JavaVanillaMethodMirror(newReceiver, symbol) def apply(args: Any*): Any = jinvoke(jmeth, receiver, args) } + private class JavaVanillaMethodMirror0(receiver: Any, symbol: MethodSymbol) + extends JavaVanillaMethodMirror(receiver, symbol) { + override def bind(newReceiver: Any) = new JavaVanillaMethodMirror0(newReceiver, symbol) + override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver) + } + + private class JavaVanillaMethodMirror1(receiver: Any, symbol: MethodSymbol) + extends JavaVanillaMethodMirror(receiver, symbol) { + override def bind(newReceiver: Any) = new JavaVanillaMethodMirror1(newReceiver, symbol) + override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef]) + } + + private class JavaVanillaMethodMirror2(receiver: Any, symbol: MethodSymbol) + extends JavaVanillaMethodMirror(receiver, symbol) { + override def bind(newReceiver: Any) = new JavaVanillaMethodMirror2(newReceiver, symbol) + override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef]) + } + + private class JavaVanillaMethodMirror3(receiver: Any, symbol: MethodSymbol) + extends JavaVanillaMethodMirror(receiver, symbol) { + override def bind(newReceiver: Any) = new JavaVanillaMethodMirror3(newReceiver, symbol) + override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef]) + } + + private class JavaVanillaMethodMirror4(receiver: Any, symbol: MethodSymbol) + extends JavaVanillaMethodMirror(receiver, symbol) { + override def bind(newReceiver: Any) = new JavaVanillaMethodMirror4(newReceiver, symbol) + override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef], args(3).asInstanceOf[AnyRef]) + } + private class JavaByNameMethodMirror(val receiver: Any, symbol: MethodSymbol) extends JavaMethodMirror(symbol) { + def bind(newReceiver: Any) = new JavaByNameMethodMirror(newReceiver, symbol) def apply(args: Any*): Any = { val transformed = map2(args.toList, symbol.paramss.flatten)((arg, param) => if (isByNameParamType(param.info)) () => arg else arg) jinvoke(jmeth, receiver, transformed) @@ -364,6 +408,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni private class JavaBytecodelessMethodMirror[T: ClassTag](val receiver: T, symbol: MethodSymbol) extends JavaMethodMirror(symbol) { + def bind(newReceiver: Any) = new JavaBytecodelessMethodMirror(newReceiver.asInstanceOf[T], symbol) def apply(args: Any*): Any = { // checking type conformance is too much of a hassle, so we don't do it here // actually it's not even necessary, because we manually dispatch arguments below @@ -420,6 +465,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni private class JavaConstructorMirror(val outer: AnyRef, val symbol: MethodSymbol) extends MethodMirror { + def bind(newReceiver: Any) = new JavaConstructorMirror(newReceiver.asInstanceOf[AnyRef], symbol) override val receiver = outer lazy val jconstr = { val jconstr = constructorToJava(symbol) |