Skip to content

Commit 4e9be26

Browse files
committed
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)
1 parent cd87823 commit 4e9be26

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,29 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
2424
import callGraph._
2525

2626
def rewriteClosureApplyInvocations(): Unit = {
27-
closureInstantiations foreach {
28-
case (indy, (methodNode, ownerClass)) =>
27+
implicit object closureInitOrdering extends Ordering[(InvokeDynamicInsnNode, MethodNode, ClassBType)] {
28+
// Note: this code is cleaned up in a future commit, no more tuples.
29+
override def compare(x: (InvokeDynamicInsnNode, MethodNode, ClassBType), y: (InvokeDynamicInsnNode, MethodNode, ClassBType)): Int = {
30+
val cls = x._3.internalName compareTo y._3.internalName
31+
if (cls != 0) return cls
32+
33+
val mName = x._2.name compareTo y._2.name
34+
if (mName != 0) return mName
35+
36+
val mDesc = x._2.desc compareTo y._2.desc
37+
if (mDesc != 0) return mDesc
38+
39+
def pos(indy: InvokeDynamicInsnNode) = x._2.instructions.indexOf(indy)
40+
pos(x._1) - pos(y._1)
41+
}
42+
}
43+
44+
val sorted = closureInstantiations.iterator.map({
45+
case (indy, (methodNode, ownerClass)) => (indy, methodNode, ownerClass)
46+
}).to[collection.immutable.TreeSet]
47+
48+
sorted foreach {
49+
case (indy, methodNode, ownerClass) =>
2950
val warnings = rewriteClosureApplyInvocations(indy, methodNode, ownerClass)
3051
warnings.foreach(w => backendReporting.inlinerWarning(w.pos, w.toString))
3152
}

0 commit comments

Comments
 (0)