The compiler interface subclasses `scala.tools.nsc.Global`,
and loading this new subclass before each `compile` task forces
HotSpot JIT to deoptimize larges swathes of compiled code. It's
a bit like SBT has rigged the dice to always descend the longest
ladder in a game of Snakes and Ladders.
The slowdown seems to be larger with Scala 2.12. There are a number
of variables at play, but I think the main factor here is that
we now rely on JIT to devirtualize calls to final methods in traits
whereas we used to emit static calls. JIT does a good job at this,
so long as classloading doesn't undo that good work.
This commit extends the existing `ClassLoaderCache` to encompass
the classloader that includes the compiler interface JAR. I've
resorted to adding a var to `AnalyzingCompiler` to inject the
dependency to get the cache to the spot I need it without binary
incompatible changes to the intervening method signatures.
Upon startup, javac may report errors because (for instance) because it
received incorrect flags. These errors were not correctly parsed by the
JavaErrorParser and were never reported to the user.
This commit fixes this problem by adding a new parsing rule in
JavaErrorParser: errors that start with the prefix "javac:" are now
correctly parsed and reported to the user.
Fixessbt/sbt#2256
These options can only be given to a forked Java compiler. If we run a
local java compiler, we filter these options out and emit a warning.
Fixessbt/sbt#1968
In some cases, the local java compiler may report compilation errors,
but succeed in compiling the source files (for instance, if there are
encoding problems in the source). However, the command line javac will
report a failed compilation on the same input.
To have the local java compiler behave like the forked java compiler, we
now report the compilation as failed if error messages have been
registered during compilation.
Fixessbt/sbt#2228
* IncrementalCompiler IC object now holds the actual logic to start incremental compilation (rather than AggresiveCompiler or other)
* MixedAnalyzingCompiler ONLY does anlaysis of Java/Scala code
* Moved the AnalyzingJavaCompiler into the integration library so that necessary dependencies are visible.
* Split Java analyzing compile into its own class.
* MixedAnalyzingCompiler now only does the mixing
* Start moving methods around to more-final locations
* Static analyzingCompile method now constructs a MixedAnalyzingCOmpiler and delegates to incremental compile.
* Force CompileSetup Equiv typeclass to use Equiv relations defined locally.
* Add toString methods on many of the incremental compiler datatypes.
* Remove remaining binary compatibility issues in Defaults.scala.
* Move error parser into its own file.
* Add the ability to parse Windows filenames.
* Remove existence check for the file as a mandatory.
* Add specific test for the parser.
* Create a new sbt.compiler.javac package
* Create new interfaces to control running `javac` and `javadoc` whether forked or local.
* Ensure new interfaces make use of `xsbti.Reporter`.
* Create new method on `xsbti.compiler.JavaCompiler` which takes a `xsbti.Reporter`
* Create a new mechanism to parse (more accurately) Warnings + Errors, to distinguish the two.
* Ensure older xsbti.Compiler implementations still succeed via catcing NoSuchMethodError.
* Feed new toolchain through sbt.actions.Compiler API via dirty hackery until we can break things in sbt 1.0
* Added a set of unit tests for parsing errors from Javac/Javadoc
* Added a new integration test for hidden compilerReporter key, including testing threading of javac reports.
Fixes#875, Fixes#1542, Related #1178 could be looked into/cleaned up.
Ideally, we wouldn't need to construct the classpath ourselves and instead
reuse the classpath construction code from a compiler (scalac or javac).
However, we need to ensure that we only call the compiler when needed.
Because we need to construct the classpath even when compilation might
not happen, we have to duplicate classpath construction.