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 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] =
|
def findClass(name: String): Option[AbstractFile] =
|
||||||
call[Option[AnyRef]](classPath, "findClass", classOf[String])(name).flatMap(extractClass)
|
findClass0(classPath, name).flatMap(a => extractClass0(a))
|
||||||
private def extractClass(a: AnyRef) =
|
|
||||||
call[Option[AbstractFile]](a, "binary")()
|
|
||||||
}
|
}
|
||||||
private class LegacyFinder extends ClassFinder
|
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] =
|
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)
|
if (entry eq null)
|
||||||
None
|
None
|
||||||
else
|
else
|
||||||
Some( call[AbstractFile](entry, "classFile")() )
|
Some( classFile(entry) )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
import scala.reflect.Manifest
|
import scala.reflect.Manifest
|
||||||
private def call[T <: AnyRef](on: AnyRef, name: String, tpes: Class[_]*)(args: AnyRef*)(implicit mf: Manifest[T]): T =
|
private def reflect[T](name: String, tpes: Class[_]*)(implicit mf: Manifest[T]) = new CachedMethod(name, tpes : _*)(mf)
|
||||||
{
|
|
||||||
val result = on.getClass.getMethod(name, tpes : _*).invoke(on, args : _*)
|
|
||||||
mf.erasure.cast(result).asInstanceOf[T]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
Goals/Guidelines for xsbt
|
||||||
=====
|
=====
|
||||||
As usual:
|
As usual:
|
||||||
|
|
@ -13,6 +18,10 @@ TODO
|
||||||
- allow comments in datatype definition file
|
- allow comments in datatype definition file
|
||||||
- tests for API extractor
|
- 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
|
Task engine
|
||||||
- method tasks will be normal tasks that pull the command line from a CommandLine task
|
- 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')
|
- per task configuration, including logging (e.g. 'task compile log debug')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue