1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package scala.tools.nsc
package backend.jvm
package analysis
import scala.tools.asm.tree.{AbstractInsnNode, MethodNode}
import scala.tools.asm.tree.analysis.{Frame, BasicInterpreter, Analyzer, Value}
import scala.tools.nsc.backend.jvm.BTypes._
import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._
/**
* This component hosts tools for running ASM analyzers that require access to a `BTypes` instance.
* In particular, the AsmAnalyzer class runs `computeMaxLocalsMaxStack` on the methodNode to be
* analyzed. This method in turn lives inside the BTypes assembly because it queries the per-run
* cache `maxLocalsMaxStackComputed` defined in there.
*/
class Analyzers[BT <: BTypes](val btypes: BT) {
import btypes._
/**
* A wrapper to make ASM's Analyzer a bit easier to use.
*/
class AsmAnalyzer[V <: Value](methodNode: MethodNode, classInternalName: InternalName, val analyzer: Analyzer[V] = new Analyzer(new BasicInterpreter)) {
localOpt.computeMaxLocalsMaxStack(methodNode)
analyzer.analyze(classInternalName, methodNode)
def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode)
}
/**
* See the doc comment on package object `analysis` for a discussion on performance.
*/
object AsmAnalyzer {
// jvm limit is 65535 for both number of instructions and number of locals
private def size(method: MethodNode) = method.instructions.size.toLong * method.maxLocals * method.maxLocals
// with the limits below, analysis should not take more than one second
private val nullnessSizeLimit = 5000l * 600l * 600l // 5000 insns, 600 locals
private val basicValueSizeLimit = 9000l * 1000l * 1000l
private val sourceValueSizeLimit = 8000l * 950l * 950l
def sizeOKForNullness(method: MethodNode): Boolean = size(method) < nullnessSizeLimit
def sizeOKForBasicValue(method: MethodNode): Boolean = size(method) < basicValueSizeLimit
def sizeOKForSourceValue(method: MethodNode): Boolean = size(method) < sourceValueSizeLimit
}
class ProdConsAnalyzer(val methodNode: MethodNode, classInternalName: InternalName) extends AsmAnalyzer(methodNode, classInternalName, new Analyzer(new InitialProducerSourceInterpreter)) with ProdConsAnalyzerImpl
}
|