summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-11-01 11:40:26 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-11-01 11:56:54 +0100
commita1d9656299a90d9ea4d5aa14a7873e3b4941eb59 (patch)
tree21affb2ad94f25be36b2b2c53c3f19b5c5e8a21f
parentc38235fd44f1ccb280e31a2f34f58deb59c5b2ee (diff)
downloadscala-a1d9656299a90d9ea4d5aa14a7873e3b4941eb59.tar.gz
scala-a1d9656299a90d9ea4d5aa14a7873e3b4941eb59.tar.bz2
scala-a1d9656299a90d9ea4d5aa14a7873e3b4941eb59.zip
Don't use runtime reflection from the batch compiler.
Not only does this save a big chunk of time on startup by avoiding classloading and symbol table population, but it also seems to improve steady state performance of the compiler. Theory: JIT can optimize more aggressively without the SynchronizedXxx decorators and the like being in the classloader. See "Class Heirarchy Analyis" in [1] This commit does this by: - Avoiding use of FromString in pattern matcher, instead using an established mechanism to parse system properties. - Changes FromString back to use OptManifest. AFAICT, this is now only a dependency of scala.tools.cmd.gen.Codegen, so this is just a defensive measure. The REPL still uses runtime reflection, so will pay a little performance tax. Benchmark: avg shortest 10 times 744ms # before avg shortest 10 times 675ms # after [1] https://wikis.oracle.com/display/HotSpotInternals/PerformanceTechniques
-rw-r--r--src/compiler/scala/tools/cmd/FromString.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala10
2 files changed, 16 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala
index 433bbb167e..0b074efc0f 100644
--- a/src/compiler/scala/tools/cmd/FromString.scala
+++ b/src/compiler/scala/tools/cmd/FromString.scala
@@ -6,21 +6,20 @@
package scala.tools
package cmd
-import scala.tools.nsc.io.{ File, Directory }
-import scala.reflect.runtime.{universe => ru}
-import scala.tools.reflect.StdRuntimeTags._
+import nsc.io.{ Path, File, Directory }
+import scala.reflect.OptManifest
/** A general mechanism for defining how a command line argument
* (always a String) is transformed into an arbitrary type. A few
* example instances are in the companion object, but in general
* either IntFromString will suffice or you'll want custom transformers.
*/
-abstract class FromString[+T](implicit t: ru.TypeTag[T]) extends PartialFunction[String, T] {
+abstract class FromString[+T](implicit m: OptManifest[T]) extends PartialFunction[String, T] {
def apply(s: String): T
def isDefinedAt(s: String): Boolean = true
def zero: T = apply("")
- def targetString: String = t.toString
+ def targetString: String = m.toString
}
object FromString {
@@ -29,13 +28,13 @@ object FromString {
/** Path related stringifiers.
*/
- val ExistingDir: FromString[Directory] = new FromString[Directory]()(tagOfDirectory) {
+ val ExistingDir: FromString[Directory] = new FromString[Directory] {
override def isDefinedAt(s: String) = toDir(s).isDirectory
def apply(s: String): Directory =
if (isDefinedAt(s)) toDir(s)
else cmd.runAndExit(println("'%s' is not an existing directory." format s))
}
- def ExistingDirRelativeTo(root: Directory) = new FromString[Directory]()(tagOfDirectory) {
+ def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] {
private def resolve(s: String) = (toDir(s) toAbsoluteWithRoot root).toDirectory
override def isDefinedAt(s: String) = resolve(s).isDirectory
def apply(s: String): Directory =
@@ -46,19 +45,19 @@ object FromString {
/** Argument expander, i.e. turns single argument "foo bar baz" into argument
* list "foo", "bar", "baz".
*/
- val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]]()(tagOfListOfString) {
+ val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]] {
def apply(s: String) = toArgs(s)
}
/** Identity.
*/
- implicit val StringFromString: FromString[String] = new FromString[String]()(tagOfString) {
+ implicit val StringFromString: FromString[String] = new FromString[String] {
def apply(s: String): String = s
}
/** Implicit as the most likely to be useful as-is.
*/
- implicit val IntFromString: FromString[Int] = new FromString[Int]()(tagOfInt) {
+ implicit val IntFromString: FromString[Int] = new FromString[Int] {
override def isDefinedAt(s: String) = safeToInt(s).isDefined
def apply(s: String) = safeToInt(s).get
def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None }
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 8a4e565ced..e0bc478fad 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -162,13 +162,17 @@ trait Logic extends Debugging {
// to govern how much time we spend analyzing matches for unreachability/exhaustivity
object AnalysisBudget {
- import scala.tools.cmd.FromString.IntFromString
- val max = sys.props.get("scalac.patmat.analysisBudget").collect(IntFromString.orElse{case "off" => Integer.MAX_VALUE}).getOrElse(256)
+ private val budgetProp = scala.sys.Prop[Int]("scalac.patmat.analysisBudget")
+ private val budgetOff = "off"
+ val max: Int = {
+ val DefaultBudget = 256
+ budgetProp.option.getOrElse(if (budgetProp.get.equalsIgnoreCase("off")) Integer.MAX_VALUE else DefaultBudget)
+ }
abstract class Exception(val advice: String) extends RuntimeException("CNF budget exceeded")
object exceeded extends Exception(
- s"(The analysis required more space than allowed. Please try with scalac -Dscalac.patmat.analysisBudget=${AnalysisBudget.max*2} or -Dscalac.patmat.analysisBudget=off.)")
+ s"(The analysis required more space than allowed. Please try with scalac -D${budgetProp.key}=${AnalysisBudget.max*2} or -D${budgetProp.key}=${budgetOff}.)")
}