summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2008-12-12 17:50:13 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2008-12-12 17:50:13 +0000
commitaf6be2087f350d0b941be26fc27f7667aad8cb9f (patch)
treebcc5d81940aca235e1fca0fe601ae2b941cf65d9 /src/library
parent491ebd0c2cc93a08cd6fa85288e2ae1129dcef0b (diff)
downloadscala-af6be2087f350d0b941be26fc27f7667aad8cb9f.tar.gz
scala-af6be2087f350d0b941be26fc27f7667aad8cb9f.tar.bz2
scala-af6be2087f350d0b941be26fc27f7667aad8cb9f.zip
Compilation of ApplyDynamic to reflective metho...
Compilation of ApplyDynamic to reflective method calls in CleanUp implements varied caching strategies (no caching, monomorphic inline caching and polymorphic inline caching). See "-Ystruct-dispatch" compiler argument.
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/runtime/MethodCache.scala68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/library/scala/runtime/MethodCache.scala b/src/library/scala/runtime/MethodCache.scala
new file mode 100644
index 0000000000..2c7a20285c
--- /dev/null
+++ b/src/library/scala/runtime/MethodCache.scala
@@ -0,0 +1,68 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http:/// **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ScalaRunTime.scala 16292 2008-10-18 21:32:45Z washburn $
+
+
+package scala.runtime
+
+
+import Predef._
+import java.lang.reflect.{ Method => JMethod }
+import java.lang.{ Class => JClass }
+
+/** An element of a polymorphic object cache.
+ * This class is refered to by the CleanUp phase. Each PolyMethodCache chain
+ * must only relate to one method as PolyMethodCache does not identify
+ * the method name and argument types. In practice, one variable will be
+ * generated per call point, and will uniquely relate to the method called
+ * at that point, making the method name and argument types irrelevant. **/
+/* TODO: if performance is acceptable, PolyMethodCache should be made generic on the method type */
+sealed abstract class MethodCache {
+ /** Searches for a cached method in the MethodCache chain that
+ * is compatible with receiver class "forReceiver". If none is cached,
+ * "null" is returned. If "null is returned", find's caller should look-
+ * up the right method using whichever means it prefers, and add it to
+ * the cache for later use. */
+ def find(forReceiver: JClass[_]): JMethod
+ def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache
+}
+
+final class EmptyMethodCache extends MethodCache {
+
+ def find(forReceiver: JClass[_]): JMethod = null
+
+ def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache =
+ new PolyMethodCache(this, forReceiver, forMethod, 1)
+
+}
+
+final class MegaMethodCache(forName: String, forParameterTypes: Array[JClass[_]]) extends MethodCache {
+
+ def find(forReceiver: JClass[_]): JMethod =
+ forReceiver.getMethod(forName, forParameterTypes:_*)
+
+ def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache = this
+
+}
+
+final class PolyMethodCache(next: MethodCache, receiver: JClass[_], method: JMethod, complexity: Int) extends MethodCache {
+
+ def find(forReceiver: JClass[_]): JMethod =
+ if (forReceiver == receiver)
+ method
+ else
+ next.find(forReceiver) // tail call is optimised, confirm with -Ylog:tailcalls
+
+ def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache =
+ if (complexity < 160) // TODO: come up with a more realistic number
+ new PolyMethodCache(this, forReceiver, forMethod, complexity + 1)
+ else
+ new MegaMethodCache(forMethod.getName, forMethod.getParameterTypes)
+
+}