summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2015-07-08 10:36:47 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2015-07-08 10:36:47 -0700
commitbac96a3a51daa002b81e7c6d7a9d9aabb8c0d62c (patch)
tree380de6fd28f40f9c249938521d4d35ecbad9077e
parentb92c3aff1ab8c76c4816bd7b1a82a0f87d787837 (diff)
parentcd878232b5747e8993bd0bae8c451c5128038130 (diff)
downloadscala-bac96a3a51daa002b81e7c6d7a9d9aabb8c0d62c.tar.gz
scala-bac96a3a51daa002b81e7c6d7a9d9aabb8c0d62c.tar.bz2
scala-bac96a3a51daa002b81e7c6d7a9d9aabb8c0d62c.zip
Merge pull request #4602 from lrytz/yoptInScala
Fix optimizer bugs and enable -Yopt:l:classpath when building scala
-rw-r--r--build-ant-macros.xml2
-rwxr-xr-xbuild.xml8
-rwxr-xr-xscripts/jobs/integrate/bootstrap4
-rwxr-xr-xscripts/jobs/validate/test2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala18
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala19
-rw-r--r--test/files/neg/incompatibleSettings.check6
-rw-r--r--test/files/neg/incompatibleSettings.flags1
-rw-r--r--test/files/neg/incompatibleSettings.scala1
-rw-r--r--test/files/neg/sealed-final-neg.flags2
-rw-r--r--test/files/neg/t4425.flags1
-rw-r--r--test/files/neg/t5639b.flags1
-rw-r--r--test/files/pos/inline-access-levels.flags2
-rw-r--r--test/files/pos/inliner2.flags2
-rw-r--r--test/files/pos/sealed-final.flags2
-rw-r--r--test/files/pos/t3420.flags2
-rw-r--r--test/files/pos/t8410.flags2
-rw-r--r--test/files/presentation/t7678/Runner.scala3
-rw-r--r--test/files/run/blame_eye_triple_eee-double.flags1
-rw-r--r--test/files/run/blame_eye_triple_eee-float.flags1
-rw-r--r--test/files/run/classfile-format-51.scala2
-rw-r--r--test/files/run/classfile-format-52.scala2
-rw-r--r--test/files/run/constant-optimization.flags2
-rw-r--r--test/files/run/dead-code-elimination.flags2
-rw-r--r--test/files/run/elidable-opt.flags2
-rw-r--r--test/files/run/elidable-opt.scala3
-rw-r--r--test/files/run/finalvar.flags2
-rw-r--r--test/files/run/icode-reader-dead-code.scala2
-rw-r--r--test/files/run/macroPlugins-namerHooks.check2
-rw-r--r--test/files/run/optimizer-array-load.flags2
-rw-r--r--test/files/run/run-bug4840.flags1
-rw-r--r--test/files/run/synchronized.flags2
-rw-r--r--test/files/run/t2106.check8
-rw-r--r--test/files/run/t2106.flags2
-rw-r--r--test/files/run/t3368-c.check24
-rw-r--r--test/files/run/t3509.flags2
-rw-r--r--test/files/run/t3569.flags2
-rw-r--r--test/files/run/t4285.flags2
-rw-r--r--test/files/run/t4935.flags2
-rw-r--r--test/files/run/t5789.scala2
-rw-r--r--test/files/run/t6102.check36
-rw-r--r--test/files/run/t6102.flags2
-rw-r--r--test/files/run/t6188.flags2
-rw-r--r--test/files/run/t7459b-optimize.flags2
-rw-r--r--test/files/run/t7582.flags2
-rw-r--r--test/files/run/t7582b.flags2
-rw-r--r--test/files/run/t8029.scala3
-rw-r--r--test/files/run/t8601.flags2
-rw-r--r--test/files/run/t8601b.flags2
-rw-r--r--test/files/run/t8601c.flags2
-rw-r--r--test/files/run/t8601d.flags2
-rw-r--r--test/files/run/t8601e.flags2
-rw-r--r--test/files/run/t9003.flags2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala42
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala74
-rw-r--r--test/junit/scala/tools/nsc/settings/SettingsTest.scala2
62 files changed, 260 insertions, 117 deletions
diff --git a/build-ant-macros.xml b/build-ant-macros.xml
index 868fb41cce..cfdb1ce70e 100644
--- a/build-ant-macros.xml
+++ b/build-ant-macros.xml
@@ -6,7 +6,7 @@
<attribute name="name"/>
<sequential>
<antcall target="@{name}">
- <param name="scalac.args.optimise" value="-optimise"/>
+ <param name="scalac.args.optimise" value="-Yopt:l:classpath"/>
</antcall>
</sequential>
</macrodef>
diff --git a/build.xml b/build.xml
index 145a64043a..38b1a7aeb4 100755
--- a/build.xml
+++ b/build.xml
@@ -19,7 +19,7 @@ ant $antArgs $scalacArgs $targets
antArgs tend to be:
-Darchives.skipxz=true
- -Dscalac.args.optimise=-optimise
+ -Dscalac.args.optimise=-Yopt:l:classpath
scalacArgs examples:
"-Dscalac.args=\"-Yrangepos\" -Dpartest.scalac_opts=\"-Yrangepos\""
@@ -79,13 +79,13 @@ TODO:
<target name="publish-opt-nodocs" description="Publishes Scala (optimized) without generating docs/testing (library/reflect/compiler/swing).">
<antcall target="publish">
<param name="docs.skip" value="1"/>
- <param name="scalac.args.optimise" value="-optimise"/>
+ <param name="scalac.args.optimise" value="-Yopt:l:classpath"/>
</antcall>
</target>
<target name="publish-core-opt-nodocs" description="Builds an untested, undocumented optimised core (library/reflect/compiler) and publishes to maven.">
<antcall target="publish-core">
<param name="docs.skip" value="1"/>
- <param name="scalac.args.optimise" value="-optimise"/>
+ <param name="scalac.args.optimise" value="-Yopt:l:classpath"/>
</antcall>
</target>
<target name="publish-core-local-nodocs" description="Builds an untested, undocumented core (library/reflect/compiler) and locally publishes to maven">
@@ -1042,7 +1042,7 @@ TODO:
<antcall target="publish-core-local">
<param name="maven.version.suffix" value="-STARR-${git.commit.sha}-SNAPSHOT"/>
<param name="docs.skip" value="1"/>
- <param name="scalac.args.optimise" value="-optimise"/>
+ <param name="scalac.args.optimise" value="-Yopt:l:classpath"/>
<param name="update.starr.version" value="alright then"/>
</antcall>
</target>
diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap
index ccc62c0d45..706a20daf4 100755
--- a/scripts/jobs/integrate/bootstrap
+++ b/scripts/jobs/integrate/bootstrap
@@ -493,7 +493,7 @@ bootstrap() {
-Dremote.snapshot.repository=NOPE\
-Dremote.release.repository=$releaseTempRepoUrl\
-Drepository.credentials.id=$releaseTempRepoCred\
- -Dscalac.args.optimise=-optimise\
+ -Dscalac.args.optimise=-Yopt:l:classpath\
-Ddocs.skip=1\
-Dlocker.skip=1\
$publishLockerPrivateTask >> $baseDir/logs/builds 2>&1
@@ -533,7 +533,7 @@ bootstrap() {
-Dremote.snapshot.repository=NOPE\
-Dremote.release.repository=$releaseTempRepoUrl\
-Drepository.credentials.id=$releaseTempRepoCred\
- -Dscalac.args.optimise=-optimise\
+ -Dscalac.args.optimise=-Yopt:l:classpath\
$antBuildTask $publishPrivateTask
# clear ivy cache (and to be sure, local as well), so the next round of sbt builds sees the fresh scala
diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test
index bedef2e458..d63d39c65d 100755
--- a/scripts/jobs/validate/test
+++ b/scripts/jobs/validate/test
@@ -10,7 +10,7 @@ case $prDryRun in
# build quick using STARR built upstream, as specified by scalaVersion
# (in that sense it's locker, since it was built with starr by that upstream job)
ant -Dstarr.version=$scalaVersion \
- -Dscalac.args.optimise=-optimise \
+ -Dscalac.args.optimise=-Yopt:l:classpath \
-Dlocker.skip=1 -Dextra.repo.url=$prRepoUrl \
$testExtraArgs ${testTarget-test.core docs.done}
;;
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 965f984367..5cb31c1b64 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1373,7 +1373,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
unitbuf += unit
compiledFiles += unit.source.file.path
}
- private def checkDeprecatedSettings(unit: CompilationUnit) {
+ private def warnDeprecatedAndConflictingSettings(unit: CompilationUnit) {
// issue warnings for any usage of deprecated settings
settings.userSetSettings filter (_.isDeprecated) foreach { s =>
currentRun.reporting.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get)
@@ -1383,6 +1383,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
currentRun.reporting.deprecationWarning(NoPosition, settings.target.name + ":" + settings.target.value + " is deprecated and has no effect, setting to " + supportedTarget)
settings.target.value = supportedTarget
}
+ settings.conflictWarning.foreach(reporter.warning(NoPosition, _))
}
/* An iterator returning all the units being compiled in this run */
@@ -1473,7 +1474,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def compileSources(sources: List[SourceFile]) = if (!reporter.hasErrors) {
def checkDeprecations() = {
- checkDeprecatedSettings(newCompilationUnit(""))
+ warnDeprecatedAndConflictingSettings(newCompilationUnit(""))
reporting.summarizeErrors()
}
@@ -1495,7 +1496,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val startTime = currentTime
reporter.reset()
- checkDeprecatedSettings(unitbuf.head)
+ warnDeprecatedAndConflictingSettings(unitbuf.head)
globalPhase = fromPhase
while (globalPhase.hasNext && !reporter.hasErrors) {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
index 0df1b2029d..cd7e0b83e8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
@@ -10,6 +10,7 @@ import java.io.{StringWriter, PrintWriter}
import scala.tools.asm.util.{CheckClassAdapter, TraceClassVisitor, TraceMethodVisitor, Textifier}
import scala.tools.asm.{ClassWriter, Attribute, ClassReader}
import scala.collection.convert.decorateAsScala._
+import scala.tools.nsc.backend.jvm.analysis.InitialProducer
import scala.tools.nsc.backend.jvm.opt.InlineInfoAttributePrototype
object AsmUtils {
@@ -81,13 +82,16 @@ object AsmUtils {
/**
* Returns a human-readable representation of the given instruction.
*/
- def textify(insn: AbstractInsnNode): String = {
- val trace = new TraceMethodVisitor(new Textifier)
- insn.accept(trace)
- val sw = new StringWriter
- val pw = new PrintWriter(sw)
- trace.p.print(pw)
- sw.toString.trim
+ def textify(insn: AbstractInsnNode): String = insn match {
+ case _: InitialProducer =>
+ insn.toString
+ case _ =>
+ val trace = new TraceMethodVisitor(new Textifier)
+ insn.accept(trace)
+ val sw = new StringWriter
+ val pw = new PrintWriter(sw)
+ trace.p.print(pw)
+ sw.toString.trim
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index c3f71969f6..063fb81d46 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -843,7 +843,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
*
* New (http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.10.1)
* - Requires consistent stack map frames. GenBCode always generates stack frames.
- * or higher.
* - In practice: the ASM library computes stack map frames for us (ClassWriter). Emitting
* correct frames after an ATHROW is probably complex, so ASM uses the following strategy:
* - Every time when generating an ATHROW, a new basic block is started.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index c6db591c5f..0f381a4325 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -728,11 +728,11 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
mv.visitVarInsn(ALOAD, 1)
mv.visitFieldInsn(PUTSTATIC, clazz.javaBinaryName.toString, "$deserializeLambdaCache$", "Ljava/util/Map;")
mv.visitLabel(l0)
- mv.visitFrame(asm.Opcodes.F_APPEND,1, Array("java/util/Map"), 0, null)
+ mv.visitFieldInsn(GETSTATIC, "scala/runtime/LambdaDeserializer$", "MODULE$", "Lscala/runtime/LambdaDeserializer$;")
mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false)
mv.visitVarInsn(ALOAD, 1)
mv.visitVarInsn(ALOAD, 0)
- mv.visitMethodInsn(INVOKESTATIC, "scala/runtime/LambdaDeserializer", "deserializeLambda", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/util/Map;Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", false)
+ mv.visitMethodInsn(INVOKEVIRTUAL, "scala/runtime/LambdaDeserializer$", "deserializeLambda", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/util/Map;Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", false)
mv.visitInsn(ARETURN)
mv.visitEnd()
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
index ad75363102..5d56861ffc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
@@ -103,7 +103,11 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName)
def initialProducersForValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
def initialProducers(insn: AbstractInsnNode, producedSlot: Int): Set[AbstractInsnNode] = {
if (isCopyOperation(insn)) {
- _initialProducersCache.getOrElseUpdate((insn, producedSlot), {
+ val key = (insn, producedSlot)
+ _initialProducersCache.getOrElseUpdate(key, {
+ // prevent infinite recursion if an instruction is its own producer or consumer
+ // see cyclicProdCons in ProdConsAnalyzerTest
+ _initialProducersCache(key) = Set.empty
val (sourceValue, sourceValueSlot) = copyOperationSourceValue(insn, producedSlot)
sourceValue.insns.iterator.asScala.flatMap(initialProducers(_, sourceValueSlot)).toSet
})
@@ -121,7 +125,11 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName)
def ultimateConsumersOfValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
def ultimateConsumers(insn: AbstractInsnNode, consumedSlot: Int): Set[AbstractInsnNode] = {
if (isCopyOperation(insn)) {
- _ultimateConsumersCache.getOrElseUpdate((insn, consumedSlot), {
+ val key = (insn, consumedSlot)
+ _ultimateConsumersCache.getOrElseUpdate(key, {
+ // prevent infinite recursion if an instruction is its own producer or consumer
+ // see cyclicProdCons in ProdConsAnalyzerTest
+ _ultimateConsumersCache(key) = Set.empty
for {
producedSlot <- copyOperationProducedValueSlots(insn, consumedSlot)
consumer <- consumersOfValueAt(insn.getNext, producedSlot)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
index 0ec550981a..cd36fd8bba 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
@@ -12,7 +12,7 @@ import scala.collection.mutable
import scala.reflect.internal.util.Collections._
import scala.tools.asm.commons.CodeSizeEvaluator
import scala.tools.asm.tree.analysis._
-import scala.tools.asm.{MethodWriter, ClassWriter, Label, Opcodes}
+import scala.tools.asm.{MethodWriter, ClassWriter, Label, Opcodes, Type}
import scala.tools.asm.tree._
import GenBCode._
import scala.collection.convert.decorateAsScala._
@@ -331,6 +331,26 @@ object BytecodeUtils {
}
/**
+ * This method is used by optimizer components to eliminate phantom values of instruction
+ * that load a value of type `Nothing$` or `Null$`. Such values on the stack don't interact well
+ * with stack map frames.
+ *
+ * For example, `opt.getOrElse(throw e)` is re-written to an invocation of the lambda body, a
+ * method with return type `Nothing$`. Similarly for `opt.getOrElse(null)` and `Null$`.
+ *
+ * During bytecode generation this is handled by BCodeBodyBuilder.adapt. See the comment in that
+ * method which explains the issue with such phantom values.
+ */
+ def fixLoadedNothingOrNullValue(loadedType: Type, loadInstr: AbstractInsnNode, methodNode: MethodNode, bTypes: BTypes): Unit = {
+ if (loadedType == bTypes.coreBTypes.RT_NOTHING.toASMType) {
+ methodNode.instructions.insert(loadInstr, new InsnNode(Opcodes.ATHROW))
+ } else if (loadedType == bTypes.coreBTypes.RT_NULL.toASMType) {
+ methodNode.instructions.insert(loadInstr, new InsnNode(Opcodes.ACONST_NULL))
+ methodNode.instructions.insert(loadInstr, new InsnNode(Opcodes.POP))
+ }
+ }
+
+ /**
* A wrapper to make ASM's Analyzer a bit easier to use.
*/
class AsmAnalyzer[V <: Value](methodNode: MethodNode, classInternalName: InternalName, interpreter: Interpreter[V] = new BasicInterpreter) {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
index 1648a53ed8..743a454678 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
@@ -283,6 +283,10 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
val isInterface = bodyOpcode == INVOKEINTERFACE
val bodyInvocation = new MethodInsnNode(bodyOpcode, lambdaBodyHandle.getOwner, lambdaBodyHandle.getName, lambdaBodyHandle.getDesc, isInterface)
methodNode.instructions.insertBefore(invocation, bodyInvocation)
+
+ val returnType = Type.getReturnType(lambdaBodyHandle.getDesc)
+ fixLoadedNothingOrNullValue(returnType, bodyInvocation, methodNode, btypes) // see comment of that method
+
methodNode.instructions.remove(invocation)
// update the call graph
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index c8251a542c..dedf268b56 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -136,7 +136,7 @@ trait ScalaSettings extends AbsScalaSettings
val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
val reporter = StringSetting ("-Xreporter", "classname", "Specify a custom reporter for compiler messages.", "scala.tools.nsc.reporters.ConsoleReporter")
val strictInference = BooleanSetting ("-Xstrict-inference", "Don't infer known-unsound types")
- val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see SI-8126.", initial = ScalaVersion("2.11"))
+ val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see SI-8126.", initial = ScalaVersion("2.12"))
val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")
@@ -388,6 +388,23 @@ trait ScalaSettings extends AbsScalaSettings
val Normal = "normal"
val Discard = "discard"
}
+
+ def conflictWarning: Option[String] = {
+ def oldOptimiseFlagsInGenBCode: Option[String] = {
+ val optFlags: List[Setting] = if (optimise.value) List(optimise) else optimiseSettings.filter(_.value)
+ if (isBCodeActive && optFlags.nonEmpty) {
+ val msg = s"""Compiler settings for the 2.11 optimizer (${optFlags.map(_.name).mkString(", ")}) are incompatible with -Ybackend:GenBCode (which is the default in 2.12).
+ |The optimizer settings are ignored. See -Yopt:help for enabling the new optimizer in 2.12.""".stripMargin
+ Some(msg)
+ } else
+ None
+ }
+
+ List(oldOptimiseFlagsInGenBCode /*, moreToCome */).flatten match {
+ case Nil => None
+ case warnings => Some("Conflicting compiler settings were detected. Some settings will be ignored.\n" + warnings.mkString("\n"))
+ }
+ }
}
object ClassPathRepresentationType {
diff --git a/test/files/neg/incompatibleSettings.check b/test/files/neg/incompatibleSettings.check
new file mode 100644
index 0000000000..0f28d41825
--- /dev/null
+++ b/test/files/neg/incompatibleSettings.check
@@ -0,0 +1,6 @@
+warning: Conflicting compiler settings were detected. Some settings will be ignored.
+Compiler settings for the 2.11 optimizer (-optimise) are incompatible with -Ybackend:GenBCode (which is the default in 2.12).
+The optimizer settings are ignored. See -Yopt:help for enabling the new optimizer in 2.12.
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/test/files/neg/incompatibleSettings.flags b/test/files/neg/incompatibleSettings.flags
new file mode 100644
index 0000000000..00dd9c1c24
--- /dev/null
+++ b/test/files/neg/incompatibleSettings.flags
@@ -0,0 +1 @@
+-optimise -Ybackend:GenBCode -Xfatal-warnings
diff --git a/test/files/neg/incompatibleSettings.scala b/test/files/neg/incompatibleSettings.scala
new file mode 100644
index 0000000000..826a1a5bc2
--- /dev/null
+++ b/test/files/neg/incompatibleSettings.scala
@@ -0,0 +1 @@
+class C
diff --git a/test/files/neg/sealed-final-neg.flags b/test/files/neg/sealed-final-neg.flags
index cfabf7a5b4..3f0fcd2201 100644
--- a/test/files/neg/sealed-final-neg.flags
+++ b/test/files/neg/sealed-final-neg.flags
@@ -1 +1 @@
--Xfatal-warnings -Yinline-warnings -optimise \ No newline at end of file
+-Xfatal-warnings -Ybackend:GenASM -Yinline-warnings -optimise \ No newline at end of file
diff --git a/test/files/neg/t4425.flags b/test/files/neg/t4425.flags
deleted file mode 100644
index 1182725e86..0000000000
--- a/test/files/neg/t4425.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize \ No newline at end of file
diff --git a/test/files/neg/t5639b.flags b/test/files/neg/t5639b.flags
new file mode 100644
index 0000000000..90b87663af
--- /dev/null
+++ b/test/files/neg/t5639b.flags
@@ -0,0 +1 @@
+-Xsource:2.11 \ No newline at end of file
diff --git a/test/files/pos/inline-access-levels.flags b/test/files/pos/inline-access-levels.flags
index 882f40f050..9bda07eb6c 100644
--- a/test/files/pos/inline-access-levels.flags
+++ b/test/files/pos/inline-access-levels.flags
@@ -1 +1 @@
--optimise -Xfatal-warnings -Yinline-warnings
+-optimise -Ybackend:GenASM -Xfatal-warnings -Yinline-warnings
diff --git a/test/files/pos/inliner2.flags b/test/files/pos/inliner2.flags
index ea03113c66..bff4bb8afa 100644
--- a/test/files/pos/inliner2.flags
+++ b/test/files/pos/inliner2.flags
@@ -1 +1 @@
--optimise -Xfatal-warnings \ No newline at end of file
+-optimise -Ybackend:GenASM -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/sealed-final.flags b/test/files/pos/sealed-final.flags
index cfabf7a5b4..63f5e65527 100644
--- a/test/files/pos/sealed-final.flags
+++ b/test/files/pos/sealed-final.flags
@@ -1 +1 @@
--Xfatal-warnings -Yinline-warnings -optimise \ No newline at end of file
+-Xfatal-warnings -Yinline-warnings -Ybackend:GenASM -optimise \ No newline at end of file
diff --git a/test/files/pos/t3420.flags b/test/files/pos/t3420.flags
index ea03113c66..bff4bb8afa 100644
--- a/test/files/pos/t3420.flags
+++ b/test/files/pos/t3420.flags
@@ -1 +1 @@
--optimise -Xfatal-warnings \ No newline at end of file
+-optimise -Ybackend:GenASM -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t8410.flags b/test/files/pos/t8410.flags
index dcd5943c2f..2f32e3b26a 100644
--- a/test/files/pos/t8410.flags
+++ b/test/files/pos/t8410.flags
@@ -1 +1 @@
--optimise -Xfatal-warnings -deprecation:false -Yinline-warnings:false
+-optimise -Ybackend:GenASM -Xfatal-warnings -deprecation:false -Yinline-warnings:false
diff --git a/test/files/presentation/t7678/Runner.scala b/test/files/presentation/t7678/Runner.scala
index 14d6dc2a70..e45f057ff1 100644
--- a/test/files/presentation/t7678/Runner.scala
+++ b/test/files/presentation/t7678/Runner.scala
@@ -1,3 +1,6 @@
+/*
+ * filter: inliner warnings; re-run with
+ */
import scala.tools.nsc.interactive.tests._
import scala.reflect.internal.util._
diff --git a/test/files/run/blame_eye_triple_eee-double.flags b/test/files/run/blame_eye_triple_eee-double.flags
deleted file mode 100644
index c9b68d70dc..0000000000
--- a/test/files/run/blame_eye_triple_eee-double.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise
diff --git a/test/files/run/blame_eye_triple_eee-float.flags b/test/files/run/blame_eye_triple_eee-float.flags
deleted file mode 100644
index c9b68d70dc..0000000000
--- a/test/files/run/blame_eye_triple_eee-float.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise
diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala
index da322bb5d9..0e90b881e5 100644
--- a/test/files/run/classfile-format-51.scala
+++ b/test/files/run/classfile-format-51.scala
@@ -16,7 +16,7 @@ import Opcodes._
// verify. So the test includes a version check that short-circuites the whole test
// on JDK 6
object Test extends DirectTest {
- override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
+ override def extraSettings: String = "-Yopt:l:classpath -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
def generateClass() {
val invokerClassName = "DynamicInvoker"
diff --git a/test/files/run/classfile-format-52.scala b/test/files/run/classfile-format-52.scala
index e278d40b8b..ebd0826303 100644
--- a/test/files/run/classfile-format-52.scala
+++ b/test/files/run/classfile-format-52.scala
@@ -13,7 +13,7 @@ import Opcodes._
// By its nature the test can only work on JDK 8+ because under JDK 7- the
// interface won't verify.
object Test extends DirectTest {
- override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
+ override def extraSettings: String = "-Yopt:l:classpath -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
def generateInterface() {
val interfaceName = "HasDefaultMethod"
diff --git a/test/files/run/constant-optimization.flags b/test/files/run/constant-optimization.flags
index c9b68d70dc..6c9965e749 100644
--- a/test/files/run/constant-optimization.flags
+++ b/test/files/run/constant-optimization.flags
@@ -1 +1 @@
--optimise
+-optimise -Ybackend:GenASM
diff --git a/test/files/run/dead-code-elimination.flags b/test/files/run/dead-code-elimination.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/run/dead-code-elimination.flags
+++ b/test/files/run/dead-code-elimination.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/run/elidable-opt.flags b/test/files/run/elidable-opt.flags
index 62897ff218..6537d2f57a 100644
--- a/test/files/run/elidable-opt.flags
+++ b/test/files/run/elidable-opt.flags
@@ -1 +1 @@
--optimise -Xelide-below 900
+-optimise -Ybackend:GenASM -Xelide-below 900
diff --git a/test/files/run/elidable-opt.scala b/test/files/run/elidable-opt.scala
index a2f29d2caf..ebada46de8 100644
--- a/test/files/run/elidable-opt.scala
+++ b/test/files/run/elidable-opt.scala
@@ -1,3 +1,6 @@
+/*
+ * filter: inliner warnings; re-run with
+ */
import annotation._
import elidable._
diff --git a/test/files/run/finalvar.flags b/test/files/run/finalvar.flags
index aee3039bec..8d9be3d62e 100644
--- a/test/files/run/finalvar.flags
+++ b/test/files/run/finalvar.flags
@@ -1 +1 @@
--Yoverride-vars -Yinline \ No newline at end of file
+-Yoverride-vars -Yinline -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/icode-reader-dead-code.scala b/test/files/run/icode-reader-dead-code.scala
index 00ba58829f..535ef2a2e2 100644
--- a/test/files/run/icode-reader-dead-code.scala
+++ b/test/files/run/icode-reader-dead-code.scala
@@ -36,7 +36,7 @@ object Test extends DirectTest {
// If inlining fails, the compiler will issue an inliner warning that is not present in the
// check file
- compileString(newCompiler("-usejavacp", "-optimise"))(bCode)
+ compileString(newCompiler("-usejavacp", "-optimise", "-Ybackend:GenASM"))(bCode)
}
def readClass(file: String) = {
diff --git a/test/files/run/macroPlugins-namerHooks.check b/test/files/run/macroPlugins-namerHooks.check
index c2db5935d4..56b170cbd9 100644
--- a/test/files/run/macroPlugins-namerHooks.check
+++ b/test/files/run/macroPlugins-namerHooks.check
@@ -28,7 +28,7 @@ enterStat(<synthetic> val C$1: C = x$1.asInstanceOf[C])
enterSym(def <init>() = { super.<init>(); () })
enterSym(final override <synthetic> def toString() = "C")
enterSym(case <synthetic> def apply(x: Int, y: Int): C = new C(x, y))
-enterSym(case <synthetic> def unapply(x$0: C) = if (x$0.==(null)) scala.this.None else Some(scala.Tuple2(x$0.x, x$0.y)))
+enterSym(case <synthetic> def unapply(x$0: C): _root_.scala.Option[scala.Tuple2[Int, Int]] = if (x$0.==(null)) scala.this.None else Some(scala.Tuple2(x$0.x, x$0.y)))
enterStat(def <init>() = { super.<init>(); () })
enterStat(final override <synthetic> def toString() = "C")
enterSym(def <init>() = { super.<init>(); () })
diff --git a/test/files/run/optimizer-array-load.flags b/test/files/run/optimizer-array-load.flags
index eb4d19bcb9..99bd6c895d 100644
--- a/test/files/run/optimizer-array-load.flags
+++ b/test/files/run/optimizer-array-load.flags
@@ -1 +1 @@
--optimise \ No newline at end of file
+-optimise -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/run-bug4840.flags b/test/files/run/run-bug4840.flags
deleted file mode 100644
index eb4d19bcb9..0000000000
--- a/test/files/run/run-bug4840.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise \ No newline at end of file
diff --git a/test/files/run/synchronized.flags b/test/files/run/synchronized.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/run/synchronized.flags
+++ b/test/files/run/synchronized.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/run/t2106.check b/test/files/run/t2106.check
index c6457216b5..b19165824b 100644
--- a/test/files/run/t2106.check
+++ b/test/files/run/t2106.check
@@ -1,13 +1,5 @@
-#partest !-Ybackend:GenASM
t2106.scala:7: warning: A::foo()Ljava/lang/Object; is annotated @inline but could not be inlined:
The callee A::foo()Ljava/lang/Object; contains the instruction INVOKEVIRTUAL java/lang/Object.clone ()Ljava/lang/Object;
that would cause an IllegalAccessError when inlined into class Test$.
def main(args: Array[String]): Unit = x.foo
^
-#partest -Ybackend:GenASM
-t2106.scala:7: warning: Could not inline required method foo because access level required by callee not matched by caller.
- def main(args: Array[String]): Unit = x.foo
- ^
-t2106.scala:7: warning: At the end of the day, could not inline @inline-marked method foo
- def main(args: Array[String]): Unit = x.foo
- ^
diff --git a/test/files/run/t2106.flags b/test/files/run/t2106.flags
index a2e413bb22..5d6ee831df 100644
--- a/test/files/run/t2106.flags
+++ b/test/files/run/t2106.flags
@@ -1 +1 @@
--optimise -Yinline-warnings -Yopt:l:classpath
+-Yinline-warnings -Yopt:l:classpath
diff --git a/test/files/run/t3368-c.check b/test/files/run/t3368-c.check
index e0c10cc0dd..4cbe98c577 100644
--- a/test/files/run/t3368-c.check
+++ b/test/files/run/t3368-c.check
@@ -6,8 +6,8 @@ package <empty> {
};
def x = {
val $buf = new _root_.scala.xml.NodeBuffer();
- $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye"));
- $buf.$amp$plus(new _root_.scala.xml.Text("red & black"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("red & black"));
$buf
}
};
@@ -24,7 +24,8 @@ package <empty> {
new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)
}
});
- $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("start"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye"));
$buf.$amp$plus({
{
new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)
@@ -36,7 +37,8 @@ package <empty> {
new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true)
}
});
- $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("stuff"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("red & black"));
$buf
}: _*))
}
@@ -46,18 +48,19 @@ package <empty> {
def $init$() = {
()
};
- def d = new _root_.scala.xml.Text("hello, world");
+ def d = new _root_.scala.xml.PCData("hello, world");
def e = {
val $buf = new _root_.scala.xml.NodeBuffer();
- $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
- $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
$buf
};
def f = {
{
new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
val $buf = new _root_.scala.xml.NodeBuffer();
- $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("x"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
$buf
}: _*))
}
@@ -66,7 +69,7 @@ package <empty> {
{
new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
val $buf = new _root_.scala.xml.NodeBuffer();
- $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
$buf
}: _*))
}
@@ -75,7 +78,8 @@ package <empty> {
{
new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
val $buf = new _root_.scala.xml.NodeBuffer();
- $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
$buf
}: _*))
}
diff --git a/test/files/run/t3509.flags b/test/files/run/t3509.flags
index 6933d924d3..9c59981aa9 100644
--- a/test/files/run/t3509.flags
+++ b/test/files/run/t3509.flags
@@ -1 +1 @@
--Yinline \ No newline at end of file
+-Yinline -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t3569.flags b/test/files/run/t3569.flags
index 6933d924d3..9c59981aa9 100644
--- a/test/files/run/t3569.flags
+++ b/test/files/run/t3569.flags
@@ -1 +1 @@
--Yinline \ No newline at end of file
+-Yinline -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t4285.flags b/test/files/run/t4285.flags
index eb4d19bcb9..99bd6c895d 100644
--- a/test/files/run/t4285.flags
+++ b/test/files/run/t4285.flags
@@ -1 +1 @@
--optimise \ No newline at end of file
+-optimise -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t4935.flags b/test/files/run/t4935.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/run/t4935.flags
+++ b/test/files/run/t4935.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/run/t5789.scala b/test/files/run/t5789.scala
index 2903dada48..c8d95f2153 100644
--- a/test/files/run/t5789.scala
+++ b/test/files/run/t5789.scala
@@ -5,7 +5,7 @@ import scala.tools.partest.ReplTest
object Test extends ReplTest {
- override def extraSettings = "-Yinline"
+ override def extraSettings = "-Yinline -Ybackend:GenASM"
def code = """
val n = 2
() => n
diff --git a/test/files/run/t6102.check b/test/files/run/t6102.check
index 395864f57c..ce01362503 100644
--- a/test/files/run/t6102.check
+++ b/test/files/run/t6102.check
@@ -1,37 +1 @@
-[running phase parser on t6102.scala]
-[running phase namer on t6102.scala]
-[running phase packageobjects on t6102.scala]
-[running phase typer on t6102.scala]
-[running phase patmat on t6102.scala]
-[running phase superaccessors on t6102.scala]
-[running phase extmethods on t6102.scala]
-[running phase pickler on t6102.scala]
-[running phase refchecks on t6102.scala]
-[running phase uncurry on t6102.scala]
-[running phase tailcalls on t6102.scala]
-[running phase specialize on t6102.scala]
-[running phase explicitouter on t6102.scala]
-[running phase erasure on t6102.scala]
-[running phase posterasure on t6102.scala]
-[running phase lazyvals on t6102.scala]
-[running phase lambdalift on t6102.scala]
-[running phase constructors on t6102.scala]
-[running phase flatten on t6102.scala]
-[running phase mixin on t6102.scala]
-[running phase cleanup on t6102.scala]
-[running phase delambdafy on t6102.scala]
-[running phase icode on t6102.scala]
-#partest -optimise
-[running phase inliner on t6102.scala]
-[running phase inlinehandlers on t6102.scala]
-[running phase closelim on t6102.scala]
-[running phase constopt on t6102.scala]
-#partest
-[running phase dce on t6102.scala]
-#partest -Ybackend:GenASM
-[running phase jvm on icode]
-#partest !-Ybackend:GenASM
-[running phase jvm on t6102.scala]
-[running phase jvm on t6102.scala]
-#partest
hello
diff --git a/test/files/run/t6102.flags b/test/files/run/t6102.flags
index 726e2a997f..db58cf3b4c 100644
--- a/test/files/run/t6102.flags
+++ b/test/files/run/t6102.flags
@@ -1 +1 @@
--Ydead-code -Ydebug -Xfatal-warnings
+-Yopt:l:classpath -Xfatal-warnings
diff --git a/test/files/run/t6188.flags b/test/files/run/t6188.flags
index 0ebca3e7af..b9bb09167e 100644
--- a/test/files/run/t6188.flags
+++ b/test/files/run/t6188.flags
@@ -1 +1 @@
- -optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/run/t7459b-optimize.flags b/test/files/run/t7459b-optimize.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/run/t7459b-optimize.flags
+++ b/test/files/run/t7459b-optimize.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/run/t7582.flags b/test/files/run/t7582.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/run/t7582.flags
+++ b/test/files/run/t7582.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t7582b.flags b/test/files/run/t7582b.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/run/t7582b.flags
+++ b/test/files/run/t7582b.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t8029.scala b/test/files/run/t8029.scala
index dbd5c41387..62629d51bc 100644
--- a/test/files/run/t8029.scala
+++ b/test/files/run/t8029.scala
@@ -1,3 +1,6 @@
+/*
+ * filter: inliner warning; re-run with
+ */
import scala.tools.partest._
import scala.tools.nsc._
diff --git a/test/files/run/t8601.flags b/test/files/run/t8601.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/run/t8601.flags
+++ b/test/files/run/t8601.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t8601b.flags b/test/files/run/t8601b.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/run/t8601b.flags
+++ b/test/files/run/t8601b.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t8601c.flags b/test/files/run/t8601c.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/run/t8601c.flags
+++ b/test/files/run/t8601c.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t8601d.flags b/test/files/run/t8601d.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/run/t8601d.flags
+++ b/test/files/run/t8601d.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/run/t8601e.flags b/test/files/run/t8601e.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/run/t8601e.flags
+++ b/test/files/run/t8601e.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/run/t9003.flags b/test/files/run/t9003.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/run/t9003.flags
+++ b/test/files/run/t9003.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
index 9af9ef54fc..a5b3faced8 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
@@ -246,4 +246,46 @@ class ProdConsAnalyzerTest extends ClearAfterClass {
testSingleInsn(a.consumersOfOutputsFrom(l2i), "IRETURN")
testSingleInsn(a.producersForInputsOf(ret), "L2I")
}
+
+ @Test
+ def cyclicProdCons(): Unit = {
+ import Opcodes._
+ val m = genMethod(descriptor = "(I)I")(
+ Label(1),
+ VarOp(ILOAD, 1),
+ IntOp(BIPUSH, 10),
+ Op(IADD), // consumer of the above ILOAD
+
+ Op(ICONST_0),
+ Jump(IF_ICMPNE, Label(2)),
+
+ VarOp(ILOAD, 1),
+ VarOp(ISTORE, 1),
+ Jump(GOTO, Label(1)),
+
+ Label(2),
+ IntOp(BIPUSH, 9),
+ Op(IRETURN)
+ )
+ m.maxLocals = 2
+ m.maxStack = 2
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(iadd) = findInstr(m, "IADD")
+ val firstLoad = iadd.getPrevious.getPrevious
+ assert(firstLoad.getOpcode == ILOAD)
+ val secondLoad = findInstr(m, "ISTORE").head.getPrevious
+ assert(secondLoad.getOpcode == ILOAD)
+
+ testSingleInsn(a.producersForValueAt(iadd, 2), "ILOAD")
+ testSingleInsn(a.initialProducersForValueAt(iadd, 2), "ParameterProducer(1)")
+ testMultiInsns(a.producersForInputsOf(firstLoad), List("ParameterProducer", "ISTORE"))
+ testMultiInsns(a.producersForInputsOf(secondLoad), List("ParameterProducer", "ISTORE"))
+
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(firstLoad), "IADD")
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(secondLoad), "IADD")
+
+ testSingleInsn(a.consumersOfOutputsFrom(firstLoad), "IADD")
+ testSingleInsn(a.consumersOfOutputsFrom(secondLoad), "ISTORE")
+ }
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala
new file mode 100644
index 0000000000..69eed1f75d
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala
@@ -0,0 +1,74 @@
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.collection.generic.Clearable
+import scala.collection.mutable.ListBuffer
+import scala.reflect.internal.util.BatchSourceFile
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import scala.tools.asm.tree._
+import scala.tools.asm.tree.analysis._
+import scala.tools.nsc.backend.jvm.opt.BytecodeUtils.AsmAnalyzer
+import scala.tools.nsc.io._
+import scala.tools.nsc.reporters.StoreReporter
+import scala.tools.testing.AssertUtil._
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+import AsmUtils._
+
+import BackendReporting._
+
+import scala.collection.convert.decorateAsScala._
+import scala.tools.testing.ClearAfterClass
+
+object ClosureOptimizerTest extends ClearAfterClass.Clearable {
+ var compiler = newCompiler(extraArgs = "-Yopt:l:classpath -Yopt-warnings")
+ def clear(): Unit = { compiler = null }
+}
+
+@RunWith(classOf[JUnit4])
+class ClosureOptimizerTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = ClosureOptimizerTest
+
+ val compiler = ClosureOptimizerTest.compiler
+
+ @Test
+ def nothingTypedClosureBody(): Unit = {
+ val code =
+ """abstract class C {
+ | def isEmpty: Boolean
+ | @inline final def getOrElse[T >: C](f: => T) = if (isEmpty) f else this
+ | def t = getOrElse(throw new Error(""))
+ |}
+ """.stripMargin
+
+ val List(c) = compileClasses(compiler)(code)
+ val t = c.methods.asScala.toList.find(_.name == "t").get
+ val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$")
+ assert(bodyCall.getNext.getOpcode == ATHROW)
+ }
+
+ @Test
+ def nullTypedClosureBody(): Unit = {
+ val code =
+ """abstract class C {
+ | def isEmpty: Boolean
+ | @inline final def getOrElse[T >: C](f: => T) = if (isEmpty) f else this
+ | def t = getOrElse(null)
+ |}
+ """.stripMargin
+
+ val List(c) = compileClasses(compiler)(code)
+ val t = c.methods.asScala.toList.find(_.name == "t").get
+ val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$")
+ assert(bodyCall.getNext.getOpcode == POP)
+ assert(bodyCall.getNext.getNext.getOpcode == ACONST_NULL)
+ }
+}
diff --git a/test/junit/scala/tools/nsc/settings/SettingsTest.scala b/test/junit/scala/tools/nsc/settings/SettingsTest.scala
index 1a2d695d68..a0015f4465 100644
--- a/test/junit/scala/tools/nsc/settings/SettingsTest.scala
+++ b/test/junit/scala/tools/nsc/settings/SettingsTest.scala
@@ -172,7 +172,7 @@ class SettingsTest {
assert(residual.isEmpty)
assertTrue(s.source.value == ScalaVersion(expected))
}
- check(expected = "2.11.0") // default
+ check(expected = "2.12.0") // default
check(expected = "2.11.0", "-Xsource:2.11")
check(expected = "2.10", "-Xsource:2.10.0")
check(expected = "2.12", "-Xsource:2.12")