Skip to content

Commit

Permalink
Merge pull request scala#4639 from lrytz/closure-opt-stability
Browse files Browse the repository at this point in the history
Fix bytecode stability when running the closure optimizer
  • Loading branch information
SethTisue committed Jul 16, 2015
2 parents 2595b11 + 0c69fd8 commit 8f0c4b4
Showing 1 changed file with 8 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,24 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
}
}

// Group the closure instantiations by method allows running the ProdConsAnalyzer only once per method.
// Also sort the instantiations: If there are multiple closure instantiations in a method, closure
// invocations need to be re-written in a consistent order for bytecode stability. The local variable
// slots for storing captured values depends on the order of rewriting.
// Grouping the closure instantiations by method allows running the ProdConsAnalyzer only once per
// method. Also sort the instantiations: If there are multiple closure instantiations in a method,
// closure invocations need to be re-written in a consistent order for bytecode stability. The local
// variable slots for storing captured values depends on the order of rewriting.
val closureInstantiationsByMethod: Map[MethodNode, immutable.TreeSet[ClosureInstantiation]] = {
closureInstantiations.values.groupBy(_.ownerMethod).mapValues(immutable.TreeSet.empty ++ _)
}

// For each closure instantiation, a list of callsites of the closure that can be re-written
// If a callsite cannot be rewritten, for example because the lambda body method is not accessible,
// a warning is returned instead.
val callsitesToRewrite: Map[ClosureInstantiation, List[Either[RewriteClosureApplyToClosureBodyFailed, (MethodInsnNode, Int)]]] = {
closureInstantiationsByMethod flatMap {
val callsitesToRewrite: List[(ClosureInstantiation, List[Either[RewriteClosureApplyToClosureBodyFailed, (MethodInsnNode, Int)]])] = {
closureInstantiationsByMethod.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.head.ownerClass.internalName)
closureInits.map(init => (init, closureCallsites(init, prodCons)))
}
closureInits.iterator.map(init => (init, closureCallsites(init, prodCons)))
}).toList // mapping to a list (not a map) to keep the sorting of closureInstantiationsByMethod
}

// Rewrite all closure callsites (or issue inliner warnings for those that cannot be rewritten)
Expand Down

0 comments on commit 8f0c4b4

Please sign in to comment.