Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 84 lines (64 sloc) 3.227 kb
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
1 /* __ *\
2 ** ________ ___ / / ___ Scala API **
2d11a5b Updated copyright notices to 2011
Antonio Cunei authored
3 ** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
4 ** __\ \/ /__/ __ |/ /__/ __ | http:/// **
5 ** /____/\___/_/ |_/____/_/ | | **
6 ** |/ **
7 \* */
8
9
10
11 package scala.runtime
12
13 import java.lang.reflect.{ Method => JMethod }
14 import java.lang.{ Class => JClass }
15
13b3d06 @paulp Working on scala.runtime.
paulp authored
16 import scala.annotation.tailrec
17
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
18 /** An element of a polymorphic object cache.
19 * This class is refered to by the CleanUp phase. Each PolyMethodCache chain
20 * must only relate to one method as PolyMethodCache does not identify
21 * the method name and argument types. In practice, one variable will be
22 * generated per call point, and will uniquely relate to the method called
23 * at that point, making the method name and argument types irrelevant. **/
24 /* TODO: if performance is acceptable, PolyMethodCache should be made generic on the method type */
25 sealed abstract class MethodCache {
26 /** Searches for a cached method in the MethodCache chain that
27 * is compatible with receiver class "forReceiver". If none is cached,
28 * "null" is returned. If "null is returned", find's caller should look-
29 * up the right method using whichever means it prefers, and add it to
30 * the cache for later use. */
31 def find(forReceiver: JClass[_]): JMethod
32 def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache
33 }
34
35 final class EmptyMethodCache extends MethodCache {
36
37 def find(forReceiver: JClass[_]): JMethod = null
38
39 def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache =
40 new PolyMethodCache(this, forReceiver, forMethod, 1)
41
42 }
43
5af0e14 Bytecode generated for structural calls is impr...
Gilles Dubochet authored
44 final class MegaMethodCache(
45 private[this] val forName: String,
46 private[this] val forParameterTypes: Array[JClass[_]]
47 ) extends MethodCache {
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
48
49 def find(forReceiver: JClass[_]): JMethod =
50 forReceiver.getMethod(forName, forParameterTypes:_*)
51
52 def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache = this
53
54 }
55
5af0e14 Bytecode generated for structural calls is impr...
Gilles Dubochet authored
56 final class PolyMethodCache(
57 private[this] val next: MethodCache,
58 private[this] val receiver: JClass[_],
59 private[this] val method: JMethod,
60 private[this] val complexity: Int
61 ) extends MethodCache {
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
62
13b3d06 @paulp Working on scala.runtime.
paulp authored
63 /** To achieve tail recursion this must be a separate method
64 * from find, because the type of next is not PolyMethodCache.
65 */
66 @tailrec private def findInternal(forReceiver: JClass[_]): JMethod =
67 if (forReceiver eq receiver) method
68 else next match {
69 case x: PolyMethodCache => x findInternal forReceiver
70 case _ => next find forReceiver
71 }
72
73 def find(forReceiver: JClass[_]): JMethod = findInternal(forReceiver)
74
75 // TODO: come up with a more realistic number
76 final private val MaxComplexity = 160
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
77
78 def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache =
13b3d06 @paulp Working on scala.runtime.
paulp authored
79 if (complexity < MaxComplexity)
80 new PolyMethodCache(this, forReceiver, forMethod, complexity + 1)
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
81 else
13b3d06 @paulp Working on scala.runtime.
paulp authored
82 new MegaMethodCache(forMethod.getName, forMethod.getParameterTypes)
af6be20 Compilation of ApplyDynamic to reflective metho...
Gilles Dubochet authored
83 }
Something went wrong with that request. Please try again.