mirror of https://github.com/sbt/sbt.git
Cache reflective lookups in the compiler interface
This commit is contained in:
parent
bf7affd344
commit
7affb3526f
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
9
notes
|
|
@ -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')
|
||||
|
|
|
|||
Loading…
Reference in New Issue