Cache reflective lookups in the compiler interface

This commit is contained in:
Mark Harrah 2009-11-24 08:56:23 -05:00
parent bf7affd344
commit 7affb3526f
3 changed files with 47 additions and 11 deletions

View File

@ -190,27 +190,27 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
}
private class NewFinder extends ClassFinder
{
private val findClass0 = reflect[Option[AnyRef]]("findClass", classOf[String])
findClass0.force(classPath) // force discovery, so that an exception is thrown if method doesn't exist
private val extractClass0 = reflect[Option[AbstractFile]]("binary")
def findClass(name: String): Option[AbstractFile] =
call[Option[AnyRef]](classPath, "findClass", classOf[String])(name).flatMap(extractClass)
private def extractClass(a: AnyRef) =
call[Option[AbstractFile]](a, "binary")()
findClass0(classPath, name).flatMap(a => extractClass0(a))
}
private class LegacyFinder extends ClassFinder
{
private val root = call[AnyRef](classPath, "root")()
private val root = { val m = reflect[AnyRef]("root"); m(classPath) }
private val find0 = reflect[AnyRef]("find", classOf[String], classOf[Boolean])
find0.force(root) // force discovery, so that an exception is thrown if method doesn't exist
private val classFile = reflect[AbstractFile]("classFile")
def findClass(name: String): Option[AbstractFile] =
{
val entry = call[AnyRef](root, "find", classOf[String], classOf[Boolean])(name, boolean2Boolean(false))
val entry = find0(root, name, boolean2Boolean(false))
if (entry eq null)
None
else
Some( call[AbstractFile](entry, "classFile")() )
Some( classFile(entry) )
}
}
import scala.reflect.Manifest
private def call[T <: AnyRef](on: AnyRef, name: String, tpes: Class[_]*)(args: AnyRef*)(implicit mf: Manifest[T]): T =
{
val result = on.getClass.getMethod(name, tpes : _*).invoke(on, args : _*)
mf.erasure.cast(result).asInstanceOf[T]
}
private def reflect[T](name: String, tpes: Class[_]*)(implicit mf: Manifest[T]) = new CachedMethod(name, tpes : _*)(mf)
}

View File

@ -0,0 +1,27 @@
package xsbt
import java.lang.ref.WeakReference
import java.lang.reflect.Method
import scala.reflect.Manifest
// replacement for structural type cache, which doesn't use weak references
// assumes type of target doesn't change
// not thread safe
private final class CachedMethod[T](name: String, tpes: Class[_]*)(mf: Manifest[T]) extends NotNull
{
private var method = new WeakReference[Method](null)
private def getMethod(on: AnyRef): Method =
{
val m = on.getClass.getMethod(name, tpes : _*)
method = new WeakReference(m)
m
}
def force(on: AnyRef) { getMethod(on) }
def apply(on: AnyRef, args: AnyRef*): T =
{
val cached = method.get
val m = if(cached ne null) cached else getMethod(on)
val result = m.invoke(on, args : _*)
mf.erasure.cast(result).asInstanceOf[T]
}
}

9
notes
View File

@ -1,3 +1,8 @@
DONE
-fix caching issue for compiler interface
-fix test ClassLoader
Goals/Guidelines for xsbt
=====
As usual:
@ -13,6 +18,10 @@ TODO
- allow comments in datatype definition file
- tests for API extractor
update 0_6_Summary to mention different output directories.
look at permgen in Josh's ScalaTest
TrapExit handles System.exit(0) as nonzero exit code
Task engine
- method tasks will be normal tasks that pull the command line from a CommandLine task
- per task configuration, including logging (e.g. 'task compile log debug')