Skip to content

Commit

Permalink
Merge pull request #9495 from retronym/merge-2.12.x-to-2.13.x-20210211
Browse files Browse the repository at this point in the history
Merge 2.12.x to 2.13.x [ci: last-only]
  • Loading branch information
lrytz committed Feb 18, 2021
2 parents c475777 + 888ef94 commit ce93562
Show file tree
Hide file tree
Showing 56 changed files with 860 additions and 280 deletions.
7 changes: 7 additions & 0 deletions project/MimaFilters.scala
Expand Up @@ -30,6 +30,13 @@ object MimaFilters extends AutoPlugin {

// #9487
ProblemFilters.exclude[MissingClassProblem]("scala.reflect.ClassTag$cache$"),

ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.RedBlackTree#Tree.redWithRight"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.RedBlackTree#Tree.redWithLeftRight"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.RedBlackTree#Tree.blackWithLeftRight"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.RedBlackTree#Tree.redWithLeft"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.RedBlackTree.partitionKeys"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.RedBlackTree.filterKeys"),
)

override val buildSettings = Seq(
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/scala/reflect/quasiquotes/Parsers.scala
Expand Up @@ -99,9 +99,9 @@ trait Parsers { self: Quasiquotes =>
override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = FunctionTypePlaceholder(argtpes, restpe)

// make q"val (x: T) = rhs" be equivalent to q"val x: T = rhs" for sake of bug compatibility (scala/bug#8211)
override def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = pat match {
case TuplePlaceholder(inParensPat :: Nil) => super.makePatDef(mods, inParensPat, rhs)
case _ => super.makePatDef(mods, pat, rhs)
override def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree, rhsPos: Position) = pat match {
case TuplePlaceholder(inParensPat :: Nil) => super.makePatDef(mods, inParensPat, rhs, rhsPos)
case _ => super.makePatDef(mods, pat, rhs, rhsPos)
}
}
import treeBuilder.{global => _, unit => _}
Expand Down
6 changes: 4 additions & 2 deletions src/compiler/scala/tools/nsc/ObjectRunner.scala
Expand Up @@ -25,8 +25,10 @@ trait CommonRunner {
* @throws java.lang.NoSuchMethodException
* @throws java.lang.reflect.InvocationTargetException
*/
def run(urls: Seq[URL], objectName: String, arguments: Seq[String]): Unit =
ScalaClassLoader.fromURLs(urls).run(objectName, arguments)
def run(urls: Seq[URL], objectName: String, arguments: Seq[String]): Unit = {
import scala.reflect.internal.util.RichClassLoader._
ScalaClassLoader.fromURLsParallelCapable(urls).run(objectName, arguments)
}

/** Catches any non-fatal exception thrown by run (in the case of InvocationTargetException,
* unwrapping it) and returns it in an Option.
Expand Down
49 changes: 29 additions & 20 deletions src/compiler/scala/tools/nsc/PipelineMain.scala
Expand Up @@ -55,10 +55,19 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe

/** Forward errors to the (current) reporter. */
protected def scalacError(msg: String): Unit = {
reporter.error(FakePos("scalac"), msg + "\n scalac -help gives more information")
reporterError(FakePos("scalac"), msg + "\n scalac -help gives more information")
}

private var reporter: Reporter = _
private def reporterEcho(pos: Position, msg: String): Unit = synchronized {
reporter.echo(pos, msg)
}
private def reporterEcho(msg: String): Unit = synchronized {
reporter.echo(NoPosition, msg)
}
private def reporterError(pos: Position, msg: String): Unit = synchronized {
reporter.echo(msg)
}

private object handler extends UncaughtExceptionHandler {
override def uncaughtException(t: Thread, e: Throwable): Unit = {
Expand Down Expand Up @@ -93,14 +102,14 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
builder.append("}\n")
val path = logDir.resolve("projects.dot")
Files.write(path, builder.toString.getBytes(java.nio.charset.StandardCharsets.UTF_8))
reporter.echo("Wrote project dependency graph to: " + path.toAbsolutePath)
reporterEcho("Wrote project dependency graph to: " + path.toAbsolutePath)
}

private case class Dependency(t: Task, isMacro: Boolean, isPlugin: Boolean)

def process(): Boolean = {
reporter = createReporter(new Settings(scalacError))
reporter.echo(s"parallelism = $parallelism, strategy = $strategy")
reporterEcho(s"parallelism = $parallelism, strategy = $strategy")

def commandFor(argFileArg: Path): Task = {
val ss = new Settings(scalacError)
Expand Down Expand Up @@ -137,13 +146,13 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
} else {
PickleExtractor.process(entry, extracted)
Files.setLastModifiedTime(extracted, sourceTimeStamp)
reporter.echo(s"Exported pickles from $entry to $extracted")
reporterEcho(s"Exported pickles from $entry to $extracted")
Files.setLastModifiedTime(extracted, sourceTimeStamp)
}
strippedAndExportedClassPath(entry) = extracted
}
exportTimer.stop()
reporter.echo(f"Exported external classpath in ${exportTimer.durationMs}%.0f ms")
reporterEcho(f"Exported external classpath in ${exportTimer.durationMs}%.0f ms")
}
}

Expand All @@ -169,22 +178,22 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
Await.result(awaitAllFutures, Duration(60, "s"))
timer.stop()
val numCompleted = allFutures.count(_.isCompleted)
reporter.echo(s"PROGRESS: $numCompleted / $numAllFutures")
reporterEcho(s"PROGRESS: $numCompleted / $numAllFutures")
return
} catch {
case _: TimeoutException =>
val numCompleted = allFutures.count(_.isCompleted)
if (numCompleted == lastNumCompleted) {
reporter.echo(s"STALLED: $numCompleted / $numAllFutures")
reporter.echo("Outline/Scala/Javac")
reporterEcho(s"STALLED: $numCompleted / $numAllFutures")
reporterEcho("Outline/Scala/Javac")
projects.map {
p =>
def toX(b: Future[_]): String = b.value match { case None => "-"; case Some(Success(_)) => "x"; case Some(Failure(_)) => "!" }
val s = List(p.outlineDoneFuture, p.groupsDoneFuture, p.javaDoneFuture).map(toX).mkString(" ")
reporter.echo(s + " " + p.label)
}
} else {
reporter.echo(s"PROGRESS: $numCompleted / $numAllFutures")
reporterEcho(s"PROGRESS: $numCompleted / $numAllFutures")
lastNumCompleted = numCompleted
}
}
Expand Down Expand Up @@ -225,9 +234,9 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe

if (parallelism == 1) {
val criticalPath = projects.maxBy(_.regularCriticalPathMs)
reporter.echo(f"Critical path: ${criticalPath.regularCriticalPathMs}%.0f ms. Wall Clock: ${timer.durationMs}%.0f ms")
reporterEcho(f"Critical path: ${criticalPath.regularCriticalPathMs}%.0f ms. Wall Clock: ${timer.durationMs}%.0f ms")
} else
reporter.echo(f" Wall Clock: ${timer.durationMs}%.0f ms")
reporterEcho(f" Wall Clock: ${timer.durationMs}%.0f ms")
case Pipeline =>
projects.foreach { p =>
val depsReady = Future.traverse(dependsOn.getOrElse(p, Nil))(task => p.dependencyReadyFuture(task))
Expand Down Expand Up @@ -264,9 +273,9 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe

if (parallelism == 1) {
val criticalPath = projects.maxBy(_.regularCriticalPathMs)
reporter.echo(f"Critical path: ${criticalPath.regularCriticalPathMs}%.0f ms. Wall Clock: ${timer.durationMs}%.0f ms")
reporterEcho(f"Critical path: ${criticalPath.regularCriticalPathMs}%.0f ms. Wall Clock: ${timer.durationMs}%.0f ms")
} else
reporter.echo(f" Wall Clock: ${timer.durationMs}%.0f ms")
reporterEcho(f" Wall Clock: ${timer.durationMs}%.0f ms")
case Traditional =>
projects.foreach { p =>
val f1 = Future.traverse(dependsOn.getOrElse(p, Nil))(_.t.javaDone.future)
Expand All @@ -289,9 +298,9 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
}
if (parallelism == 1) {
val maxFullCriticalPath: Double = projects.map(_.fullCriticalPathMs).max
reporter.echo(f"Critical path: $maxFullCriticalPath%.0f ms. Wall Clock: ${timer.durationMs}%.0f ms")
reporterEcho(f"Critical path: $maxFullCriticalPath%.0f ms. Wall Clock: ${timer.durationMs}%.0f ms")
} else {
reporter.echo(f"Wall Clock: ${timer.durationMs}%.0f ms")
reporterEcho(f"Wall Clock: ${timer.durationMs}%.0f ms")
}
}

Expand Down Expand Up @@ -340,7 +349,7 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
trace.append("]}")
val traceFile = logDir.resolve(s"build-${label}.trace")
Files.write(traceFile, trace.toString.getBytes())
reporter.echo("Chrome trace written to " + traceFile.toAbsolutePath)
reporterEcho("Chrome trace written to " + traceFile.toAbsolutePath)
}

case class Group(files: List[String]) {
Expand Down Expand Up @@ -423,7 +432,7 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
if (reporter.hasErrors)
reporter.flush()
else if (command.shouldStopWithInfo)
reporter.echo(command.getInfoMessage(result))
reporterEcho(command.getInfoMessage(result))
result.reporter = createReporter(result.settings)
result
} catch {
Expand Down Expand Up @@ -556,9 +565,9 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
Position.range(sourceFile, diagnostic.getStartPosition.toInt, diagnostic.getPosition.toInt, diagnostic.getEndPosition.toInt)
}
diagnostic.getKind match {
case Kind.ERROR => reporter.error(position, msg)
case Kind.ERROR => reporterError(position, msg)
case Kind.WARNING | Kind.MANDATORY_WARNING => Task.this.compiler.runReporting.warning(position, msg, WarningCategory.JavaSource, site = "")
case Kind.NOTE | Kind.OTHER => reporter.echo(position, msg)
case Kind.NOTE | Kind.OTHER => reporterEcho(position, msg)
}
}
}
Expand All @@ -577,7 +586,7 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
javaDone.complete(Success(()))
}
}
def log(msg: String): Unit = reporter.echo(this.label + ": " + msg)
def log(msg: String): Unit = reporterEcho(this.label + ": " + msg)
}

final class Timer() {
Expand Down
10 changes: 5 additions & 5 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -2697,10 +2697,10 @@ self =>
in.nextToken()
val lhs = commaSeparated(stripParens(noSeq.pattern2()))
val tp = typedOpt()
val rhs =
val (rhs, rhsPos) =
if (!tp.isEmpty && in.token != EQUALS) {
newmods = newmods | Flags.DEFERRED
EmptyTree
(EmptyTree, NoPosition)
} else {
accept(EQUALS)
expr() match {
Expand All @@ -2712,14 +2712,14 @@ self =>
}
placeholderParams = placeholderParams.tail
newmods = newmods | Flags.DEFAULTINIT
EmptyTree
case x => x
(EmptyTree, x.pos)
case x => (x, x.pos)
}
}
def mkDefs(p: Tree, tp: Tree, rhs: Tree): List[Tree] = {
val trees = {
val pat = if (tp.isEmpty) p else Typed(p, tp) setPos (p.pos union tp.pos)
makePatDef(newmods, pat, rhs)
makePatDef(newmods, pat, rhs, rhsPos)
}
if (newmods.isDeferred) {
trees match {
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
Expand Up @@ -143,5 +143,6 @@ abstract class TreeBuilder {
}
}

def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = gen.mkPatDef(mods, pat, rhs)
final def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree): List[ValDef] = makePatDef(mods, pat, rhs, rhs.pos)
def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree, rhsPos: Position) = gen.mkPatDef(mods, pat, rhs, rhsPos)
}
56 changes: 38 additions & 18 deletions src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
Expand Up @@ -265,6 +265,10 @@ abstract class BoxUnbox {
case c: EscapingConsumer =>
assert(keepBox, s"found escaping consumer, but box is eliminated: $c")

case Drop(insn) =>
if (keepBox) toReplace(insn) = List(getPop(1))
else toDelete += insn

case extraction =>
val (slot, tp) = localSlots(boxKind.extractedValueIndex(extraction))
val loadOps = new VarInsnNode(tp.getOpcode(ILOAD), slot) :: extraction.postExtractionAdaptationOps(tp)
Expand Down Expand Up @@ -327,31 +331,38 @@ abstract class BoxUnbox {
if (boxKind.boxedTypes.lengthCompare(1) == 0) {
// fast path for single-value boxes
allConsumers.foreach(extraction => extraction.postExtractionAdaptationOps(boxKind.boxedTypes.head) match {
case Nil =>
toDelete ++= extraction.allInsns
case Nil => extraction match {
case Drop(_) => toReplace(extraction.consumer) = boxKind.boxedTypes.map(t => getPop(t.getSize))
case _ => toDelete ++= extraction.allInsns
}
case ops =>
toReplace(extraction.consumer) = ops
toDelete ++= extraction.allInsns - extraction.consumer
})
} else {
for (extraction <- allConsumers) {
val valueIndex = boxKind.extractedValueIndex(extraction)
val replacementOps = if (valueIndex == 0) {
val pops = boxKind.boxedTypes.tail.map(t => getPop(t.getSize))
pops ::: extraction.postExtractionAdaptationOps(boxKind.boxedTypes.head)
} else {
var loadOps: List[AbstractInsnNode] = null
val replacementOps = extraction match {
case Drop(_) =>
boxKind.boxedTypes.reverseIterator.map(t => getPop(t.getSize)).toList
case _ =>
val valueIndex = boxKind.extractedValueIndex(extraction)
if (valueIndex == 0) {
val pops = boxKind.boxedTypes.tail.map(t => getPop(t.getSize))
pops ::: extraction.postExtractionAdaptationOps(boxKind.boxedTypes.head)
} else {
var loadOps: List[AbstractInsnNode] = null
val consumeStack = boxKind.boxedTypes.zipWithIndex.reverseIterator.map {
case (tp, i) =>
if (i == valueIndex) {
val resultSlot = getLocal(tp.getSize)
loadOps = new VarInsnNode(tp.getOpcode(ILOAD), resultSlot) :: extraction.postExtractionAdaptationOps(tp)
new VarInsnNode(tp.getOpcode(ISTORE), resultSlot)
} else {
getPop(tp.getSize)
}
case (tp, i) =>
if (i == valueIndex) {
val resultSlot = getLocal(tp.getSize)
loadOps = new VarInsnNode(tp.getOpcode(ILOAD), resultSlot) :: extraction.postExtractionAdaptationOps(tp)
new VarInsnNode(tp.getOpcode(ISTORE), resultSlot)
} else {
getPop(tp.getSize)
}
}.to(List)
consumeStack ::: loadOps
consumeStack ::: loadOps
}
}
toReplace(extraction.consumer) = replacementOps
toDelete ++= extraction.allInsns - extraction.consumer
Expand Down Expand Up @@ -621,7 +632,7 @@ abstract class BoxUnbox {
val afterInit = initCall.getNext
val stackTopAfterInit = prodCons.frameAt(afterInit).stackTop
val initializedInstanceCons = prodCons.consumersOfValueAt(afterInit, stackTopAfterInit)
if (initializedInstanceCons == dupConsWithoutInit && prodCons.producersForValueAt(afterInit, stackTopAfterInit) == Set(dupOp)) {
if (initializedInstanceCons == dupConsWithoutInit) {
return Some((dupOp, initCall))
}
}
Expand Down Expand Up @@ -708,6 +719,9 @@ abstract class BoxUnbox {
val success = primBoxSupertypes(kind.boxClass).contains(ti.desc)
Some(BoxedPrimitiveTypeCheck(ti, success))

case i: InsnNode if i.getOpcode == POP =>
Some(Drop(i))

case _ => None
}
}
Expand Down Expand Up @@ -761,6 +775,9 @@ abstract class BoxUnbox {
case ti: TypeInsnNode if ti.getOpcode == INSTANCEOF =>
Some(BoxedPrimitiveTypeCheck(ti, ti.desc == kind.refClass || refSupertypes.contains(ti.desc)))

case i: InsnNode if i.getOpcode == POP =>
Some(Drop(i))

case _ => None
}
}
Expand Down Expand Up @@ -824,6 +841,7 @@ abstract class BoxUnbox {
}

case _ =>
if (insn.getOpcode == POP) return Some(Drop(insn))
}
None
}
Expand Down Expand Up @@ -943,6 +961,8 @@ abstract class BoxUnbox {
case class StaticSetterOrInstanceWrite(consumer: AbstractInsnNode) extends BoxConsumer
/** `.\$isInstanceOf[T]` (can be statically proven true or false) */
case class BoxedPrimitiveTypeCheck(consumer: AbstractInsnNode, success: Boolean) extends BoxConsumer
/** POP */
case class Drop(consumer: AbstractInsnNode) extends BoxConsumer
/** An unknown box consumer */
case class EscapingConsumer(consumer: AbstractInsnNode) extends BoxConsumer
}

0 comments on commit ce93562

Please sign in to comment.