diff options
author | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2009-03-12 13:38:43 +0000 |
---|---|---|
committer | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2009-03-12 13:38:43 +0000 |
commit | 5af0e1461b7562798c3d7c3fcdce346107f5af0b (patch) | |
tree | 537a2b5d7f493e7d5fa71e1a1e320a62511edfa8 | |
parent | f2dfc4a54a562bfbbf9753a3430c4186917c9788 (diff) | |
download | scala-5af0e1461b7562798c3d7c3fcdce346107f5af0b.tar.gz scala-5af0e1461b7562798c3d7c3fcdce346107f5af0b.tar.bz2 scala-5af0e1461b7562798c3d7c3fcdce346107f5af0b.zip |
Bytecode generated for structural calls is impr...
Bytecode generated for structural calls is improved slightly. A test
shows an improvement of roughly 5% for structural methods' call times.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 54 | ||||
-rw-r--r-- | src/library/scala/runtime/MethodCache.scala | 22 |
2 files changed, 41 insertions, 35 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 52fbc7b83c..db88df5dc5 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -283,14 +283,13 @@ abstract class CleanUp extends Transform { def reflMethod$Method(forReceiver: JClass[_]): JMethod = { var method: JMethod = reflPoly$Cache.find(forReceiver) - if (method == null) { + if (method != null) + return method + else { method = forReceiver.getMethod("xyz", reflParams$Cache) reflPoly$Cache = reflPoly$Cache.add(forReceiver, method) + return method } - // At that point, method is always non-null: getMethod will have previously - // returned by throwing an exception if it can't find the method. Obviously, - // CleanUp should not generate dynamic calls that are unsound. - method } */ @@ -313,34 +312,33 @@ abstract class CleanUp extends Transform { Select(gen.mkAttributedRef(reflPolyCacheSym), methodCache_find), List(gen.mkAttributedRef(forReceiverSym)) ) - ), - If( - Apply(Select(gen.mkAttributedRef(methodSym), Object_eq), List(Literal(Constant(null)))), - Block( - List( - Assign(gen.mkAttributedRef(methodSym), - Apply( - Select(gen.mkAttributedRef(forReceiverSym), Class_getMethod), - List( - Literal(Constant(method)), - gen.mkAttributedRef(reflParamsCacheSym) - ) - ) - ), - Assign( - gen.mkAttributedRef(reflPolyCacheSym), - Apply( - Select(gen.mkAttributedRef(reflPolyCacheSym), methodCache_add), - List(gen.mkAttributedRef(forReceiverSym), gen.mkAttributedRef(methodSym)) + ) + ), + If( + Apply(Select(gen.mkAttributedRef(methodSym), Object_ne), List(Literal(Constant(null)))), + Return(gen.mkAttributedRef(methodSym)), + Block( + List( + Assign(gen.mkAttributedRef(methodSym), + Apply( + Select(gen.mkAttributedRef(forReceiverSym), Class_getMethod), + List( + Literal(Constant(method)), + gen.mkAttributedRef(reflParamsCacheSym) ) ) ), - Literal(Constant(())) + Assign( + gen.mkAttributedRef(reflPolyCacheSym), + Apply( + Select(gen.mkAttributedRef(reflPolyCacheSym), methodCache_add), + List(gen.mkAttributedRef(forReceiverSym), gen.mkAttributedRef(methodSym)) + ) + ) ), - EmptyTree + Return(gen.mkAttributedRef(methodSym)) ) - ), - gen.mkAttributedRef(methodSym) + ) ) } diff --git a/src/library/scala/runtime/MethodCache.scala b/src/library/scala/runtime/MethodCache.scala index a763329bc4..1c41c7db11 100644 --- a/src/library/scala/runtime/MethodCache.scala +++ b/src/library/scala/runtime/MethodCache.scala @@ -42,7 +42,10 @@ final class EmptyMethodCache extends MethodCache { } -final class MegaMethodCache(forName: String, forParameterTypes: Array[JClass[_]]) extends MethodCache { +final class MegaMethodCache( + private[this] val forName: String, + private[this] val forParameterTypes: Array[JClass[_]] +) extends MethodCache { def find(forReceiver: JClass[_]): JMethod = forReceiver.getMethod(forName, forParameterTypes:_*) @@ -51,18 +54,23 @@ final class MegaMethodCache(forName: String, forParameterTypes: Array[JClass[_]] } -final class PolyMethodCache(next: MethodCache, receiver: JClass[_], method: JMethod, complexity: Int) extends MethodCache { +final class PolyMethodCache( + private[this] val next: MethodCache, + private[this] val receiver: JClass[_], + private[this] val method: JMethod, + private[this] val complexity: Int +) extends MethodCache { def find(forReceiver: JClass[_]): JMethod = - if (forReceiver == receiver) - method + if (forReceiver eq receiver) + return method else - next.find(forReceiver) // tail call is optimised, confirm with -Ylog:tailcalls + return 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) + return new PolyMethodCache(this, forReceiver, forMethod, complexity + 1) else - new MegaMethodCache(forMethod.getName, forMethod.getParameterTypes) + return new MegaMethodCache(forMethod.getName, forMethod.getParameterTypes) } |