summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-09-09 20:11:27 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-09-17 22:05:05 +0200
commit7b52a12b0a4b5c7e7dcc439714baf167cf2f6e84 (patch)
tree5d5e8aa3a57be980a711cf93bf999ee5093cef1b
parent2a9466723833caae0ec7b5c48953917b62a2e910 (diff)
downloadscala-7b52a12b0a4b5c7e7dcc439714baf167cf2f6e84.tar.gz
scala-7b52a12b0a4b5c7e7dcc439714baf167cf2f6e84.tar.bz2
scala-7b52a12b0a4b5c7e7dcc439714baf167cf2f6e84.zip
Minor fixes in the optimizer
Fixes the variable indices in the local variable table (debug info) for inlined locals. After re-writing a closure invocation to the body method, mark the callsite method as potentially having dead code. The body method may return Nothing$, creating new unreachable code in the callsite method.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala1
4 files changed, 10 insertions, 7 deletions
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 df8dcc690a..ede572dfb4 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
@@ -308,14 +308,14 @@ object BytecodeUtils {
* Clone the local variable descriptors of `methodNode` and map their `start` and `end` labels
* according to the `labelMap`.
*/
- def cloneLocalVariableNodes(methodNode: MethodNode, labelMap: Map[LabelNode, LabelNode], prefix: String): List[LocalVariableNode] = {
+ def cloneLocalVariableNodes(methodNode: MethodNode, labelMap: Map[LabelNode, LabelNode], prefix: String, shift: Int): List[LocalVariableNode] = {
methodNode.localVariables.iterator().asScala.map(localVariable => new LocalVariableNode(
prefix + localVariable.name,
localVariable.desc,
localVariable.signature,
labelMap(localVariable.start),
labelMap(localVariable.end),
- localVariable.index
+ localVariable.index + shift
)).toList
}
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 30b7f2edad..1a1a6942dc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
@@ -78,10 +78,10 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
closureInstantiations.iterator.flatMap({
case (methodNode, closureInits) =>
// A lazy val to ensure the analysis only runs if necessary (the value is passed by name to `closureCallsites`)
- lazy val prodCons = new ProdConsAnalyzer(methodNode, closureInits.valuesIterator.next.ownerClass.internalName)
+ lazy val prodCons = new ProdConsAnalyzer(methodNode, closureInits.valuesIterator.next().ownerClass.internalName)
val sortedInits = immutable.TreeSet.empty ++ closureInits.values
- sortedInits.iterator.map(init => (init, closureCallsites(init, prodCons)))
- }).toList // mapping to a list (not a map) to keep the sorting of closureInstantiationsByMethod
+ sortedInits.iterator.map(init => (init, closureCallsites(init, prodCons))).filter(_._2.nonEmpty)
+ }).toList // mapping to a list (not a map) to keep the sorting
}
// Rewrite all closure callsites (or issue inliner warnings for those that cannot be rewritten)
@@ -268,6 +268,10 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
// Explanation: If the lambda body method is non-static, the receiver is a captured
// value. It can only be captured within some instance method, so we know it's non-null.
callGraph.addCallsite(bodyMethodCallsite)
+
+ // Rewriting a closure invocation may render code unreachable. For example, the body method of
+ // (x: T) => ??? has return type Nothing$, and an ATHROW is added (see fixLoadedNothingOrNullValue).
+ unreachableCodeEliminated -= ownerMethod
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
index 1550f942c7..8dff7ef446 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
@@ -406,7 +406,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
callsiteMethod.instructions.insert(callsiteInstruction, clonedInstructions)
callsiteMethod.instructions.remove(callsiteInstruction)
- callsiteMethod.localVariables.addAll(cloneLocalVariableNodes(callee, labelsMap, callee.name + "_").asJava)
+ callsiteMethod.localVariables.addAll(cloneLocalVariableNodes(callee, labelsMap, callee.name + "_", localVarShift).asJava)
callsiteMethod.tryCatchBlocks.addAll(cloneTryCatchBlockNodes(callee, labelsMap).asJava)
callsiteMethod.maxLocals += returnType.getSize + callee.maxLocals
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
index 4132710a96..f5e6653344 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
@@ -196,7 +196,6 @@ object LocalOptImpls {
a.analyze(ownerClassName, method)
val frames = a.getFrames
- val initialSize = method.instructions.size
var i = 0
var liveLabels = Set.empty[LabelNode]
var removedInstructions = Set.empty[AbstractInsnNode]