diff options
author | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2008-12-12 17:50:13 +0000 |
---|---|---|
committer | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2008-12-12 17:50:13 +0000 |
commit | af6be2087f350d0b941be26fc27f7667aad8cb9f (patch) | |
tree | bcc5d81940aca235e1fca0fe601ae2b941cf65d9 /src/library | |
parent | 491ebd0c2cc93a08cd6fa85288e2ae1129dcef0b (diff) | |
download | scala-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.scala | 68 |
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) + +} |