summaryrefslogtreecommitdiff
path: root/src/partest
diff options
context:
space:
mode:
authorVlad Ureche <vlad.ureche@gmail.com>2012-08-01 12:30:11 +0200
committerVlad Ureche <vlad.ureche@gmail.com>2012-08-04 02:06:11 +0200
commit434adb151083a658b498ffb9c3284f6bb471597a (patch)
treeab31fc86ee6aeccd5f847dac2f48dc76096d82f3 /src/partest
parent4e7bf2f519d3008411922737fab9050bd00535b0 (diff)
downloadscala-434adb151083a658b498ffb9c3284f6bb471597a.tar.gz
scala-434adb151083a658b498ffb9c3284f6bb471597a.tar.bz2
scala-434adb151083a658b498ffb9c3284f6bb471597a.zip
Want a 25% partest speedup?*
... well then, don't compile twice! Explanation: The compilation process in partest happens in 3 stages: - scala + java files, all fed to scalac (so the java signatures are loaded and the scala bytecode is generated) - java files, fed to javac (so the java bytecode is generated) - scala files, fed to scalac (so the scala bytecode correctly links to the javac-generated bytecode) While this mechanism is great to have, for simple 1-file scala tests it's overkill by compiling scala files twice. So I adjusted the compile procedure to only run the first step if java files are empty, leading to a 25% partest speedup.* Also included Seth Tisue's comment about the tests that require the three-step compilation. * as measured on test.scaladoc
Diffstat (limited to 'src/partest')
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index dc15d4475b..d7d0b5649a 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -323,10 +323,34 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP
val (scalaFiles, javaFiles) = g partition isScala
val allFiles = javaFiles ++ scalaFiles
+ /* The test can contain both java and scala files, each of which should be compiled with the corresponding
+ * compiler. Since the source files can reference each other both ways (java referencing scala classes and
+ * vice versa, the partest compilation routine attempts to reach a "bytecode fixpoint" between the two
+ * compilers -- that's when bytecode generated by each compiler implements the signatures expected by the other.
+ *
+ * In theory this property can't be guaranteed, as neither compiler can know what signatures the other
+ * compiler expects and how to implement them. (see SI-1240 for the full story)
+ *
+ * In practice, this happens in 3 steps:
+ * STEP1: feed all the files to scalac
+ * it will parse java files and obtain their expected signatures and generate bytecode for scala files
+ * STEP2: feed the java files to javac
+ * it will generate the bytecode for the java files and link to the scalac-generated bytecode for scala
+ * STEP3: only if there are both scala and java files, recompile the scala sources so they link to the correct
+ * java signatures, in case the signatures deduced by scalac from the source files were wrong. Since the
+ * bytecode for java is already in place, we only feed the scala files to scalac so it will take the
+ * java signatures from the existing javac-generated bytecode
+ */
List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) {
- case (CompileSuccess, 1) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile) // java + scala
- case (CompileSuccess, 2) if javaFiles.nonEmpty => javac(outDir, javaFiles, logFile) // java
- case (CompileSuccess, 3) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile) // scala
+ case (CompileSuccess, 1) if scalaFiles.nonEmpty =>
+ compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile)
+ case (CompileSuccess, 2) if javaFiles.nonEmpty =>
+ javac(outDir, javaFiles, logFile)
+ case (CompileSuccess, 3) if scalaFiles.nonEmpty && javaFiles.nonEmpty =>
+ // TODO: Do we actually need this? SI-1240 is known to require this, but we don't know if other tests
+ // require it: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/rFDKAcOKciU
+ compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile)
+
case (outcome, _) => outcome
}
}