summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-07-07 10:04:36 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-07-07 14:33:51 +0200
commit4e9be26c1d0ea4818b54c1f882a2972f439b6e39 (patch)
tree36eea6ee76f59e1cfcd97e0ab35caba238bcd6df
parentcd878232b5747e8993bd0bae8c451c5128038130 (diff)
downloadscala-4e9be26c1d0ea4818b54c1f882a2972f439b6e39.tar.gz
scala-4e9be26c1d0ea4818b54c1f882a2972f439b6e39.tar.bz2
scala-4e9be26c1d0ea4818b54c1f882a2972f439b6e39.zip
Fix bytecode stability
When there are multiple closure allocations and invocations in the same method, ensure that the callsites are re-written to the body methods in a consistent order. Otherwsie the bytecode is not stable (the local variable indices depend on the order in which the calls are re-written)
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala25
1 files changed, 23 insertions, 2 deletions
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 743a454678..8da209b269 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
@@ -24,8 +24,29 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
import callGraph._
def rewriteClosureApplyInvocations(): Unit = {
- closureInstantiations foreach {
- case (indy, (methodNode, ownerClass)) =>
+ implicit object closureInitOrdering extends Ordering[(InvokeDynamicInsnNode, MethodNode, ClassBType)] {
+ // Note: this code is cleaned up in a future commit, no more tuples.
+ override def compare(x: (InvokeDynamicInsnNode, MethodNode, ClassBType), y: (InvokeDynamicInsnNode, MethodNode, ClassBType)): Int = {
+ val cls = x._3.internalName compareTo y._3.internalName
+ if (cls != 0) return cls
+
+ val mName = x._2.name compareTo y._2.name
+ if (mName != 0) return mName
+
+ val mDesc = x._2.desc compareTo y._2.desc
+ if (mDesc != 0) return mDesc
+
+ def pos(indy: InvokeDynamicInsnNode) = x._2.instructions.indexOf(indy)
+ pos(x._1) - pos(y._1)
+ }
+ }
+
+ val sorted = closureInstantiations.iterator.map({
+ case (indy, (methodNode, ownerClass)) => (indy, methodNode, ownerClass)
+ }).to[collection.immutable.TreeSet]
+
+ sorted foreach {
+ case (indy, methodNode, ownerClass) =>
val warnings = rewriteClosureApplyInvocations(indy, methodNode, ownerClass)
warnings.foreach(w => backendReporting.inlinerWarning(w.pos, w.toString))
}