Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit a112422

Browse files
committed
Compiler option for disabling nullness analysis
1 parent 460e10c commit a112422

File tree

4 files changed

+23
-9
lines changed

4 files changed

+23
-9
lines changed

src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ sealed trait NullnessValue extends Value {
121121
def merge(other: NullnessValue) = NullnessValue(nullness merge other.nullness, isSize2)
122122
}
123123

124-
object NullValue extends NullnessValue { def nullness = Null; def isSize2 = false; override def toString = "Null" }
124+
object NullValue extends NullnessValue { def nullness = Null; def isSize2 = false; override def toString = "Null" }
125125
object UnknownValue1 extends NullnessValue { def nullness = Unknown; def isSize2 = false; override def toString = "Unknown1" }
126126
object UnknownValue2 extends NullnessValue { def nullness = Unknown; def isSize2 = true; override def toString = "Unknown2" }
127-
object NotNullValue extends NullnessValue { def nullness = NotNull; def isSize2 = false; override def toString = "NotNull" }
127+
object NotNullValue extends NullnessValue { def nullness = NotNull; def isSize2 = false; override def toString = "NotNull" }
128128

129129
object NullnessValue {
130130
def apply(nullness: Nullness, isSize2: Boolean): NullnessValue = {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ object BytecodeUtils {
333333
def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode)
334334
}
335335

336-
implicit class AnalyzerExtendsions[V <: Value](val analyzer: Analyzer[V]) extends AnyVal {
336+
implicit class AnalyzerExtensions[V <: Value](val analyzer: Analyzer[V]) extends AnyVal {
337337
def frameAt(instruction: AbstractInsnNode, methodNode: MethodNode): Frame[V] = analyzer.getFrames()(methodNode.instructions.indexOf(instruction))
338338
}
339339

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package backend.jvm
88
package opt
99

1010
import scala.reflect.internal.util.{NoPosition, Position}
11+
import scala.tools.asm.tree.analysis.{Value, Analyzer, BasicInterpreter}
1112
import scala.tools.asm.{Opcodes, Type}
1213
import scala.tools.asm.tree._
1314
import scala.collection.convert.decorateAsScala._
@@ -100,9 +101,21 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
100101
// call is known to be not-null, in which case we don't have to emit a null check when inlining.
101102
// It is also used to get the stack height at the call site.
102103
localOpt.minimalRemoveUnreachableCode(methodNode, definingClass.internalName)
103-
val analyzer = new NullnessAnalyzer
104+
105+
val analyzer: Analyzer[_ <: Value] = {
106+
if (compilerSettings.YoptNullnessTracking) new NullnessAnalyzer
107+
else new Analyzer(new BasicInterpreter)
108+
}
104109
analyzer.analyze(definingClass.internalName, methodNode)
105110

111+
def receiverNotNullByAnalysis(call: MethodInsnNode, numArgs: Int) = analyzer match {
112+
case nullnessAnalyzer: NullnessAnalyzer =>
113+
val frame = nullnessAnalyzer.frameAt(call, methodNode)
114+
frame.getStack(frame.getStackSize - 1 - numArgs).nullness == NotNull
115+
116+
case _ => false
117+
}
118+
106119
methodNode.instructions.iterator.asScala.collect({
107120
case call: MethodInsnNode =>
108121
val callee: Either[OptimizerWarning, Callee] = for {
@@ -131,8 +144,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
131144

132145
val receiverNotNull = call.getOpcode == Opcodes.INVOKESTATIC || {
133146
val numArgs = Type.getArgumentTypes(call.desc).length
134-
val frame = analyzer.frameAt(call, methodNode)
135-
frame.getStack(frame.getStackSize - 1 - numArgs).nullness == NotNull
147+
receiverNotNullByAnalysis(call, numArgs)
136148
}
137149

138150
Callsite(

src/compiler/scala/tools/nsc/settings/ScalaSettings.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,15 +234,16 @@ trait ScalaSettings extends AbsScalaSettings
234234
val emptyLineNumbers = Choice("empty-line-numbers", "Eliminate unnecessary line number information.")
235235
val emptyLabels = Choice("empty-labels", "Eliminate and collapse redundant labels in the bytecode.")
236236
val compactLocals = Choice("compact-locals", "Eliminate empty slots in the sequence of local variables.")
237-
val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled")
238-
val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath")
237+
val nullnessTracking = Choice("nullness-tracking", "Track nullness / non-nullness of local variables and apply optimizations.")
238+
val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled.")
239+
val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath.")
239240

240241
val lNone = Choice("l:none", "Don't enable any optimizations.")
241242

242243
private val defaultChoices = List(unreachableCode)
243244
val lDefault = Choice("l:default", "Enable default optimizations: "+ defaultChoices.mkString(","), expandsTo = defaultChoices)
244245

245-
private val methodChoices = List(unreachableCode, simplifyJumps, emptyLineNumbers, emptyLabels, compactLocals)
246+
private val methodChoices = List(unreachableCode, simplifyJumps, emptyLineNumbers, emptyLabels, compactLocals, nullnessTracking)
246247
val lMethod = Choice("l:method", "Enable intra-method optimizations: "+ methodChoices.mkString(","), expandsTo = methodChoices)
247248

248249
private val projectChoices = List(lMethod, inlineProject)
@@ -264,6 +265,7 @@ trait ScalaSettings extends AbsScalaSettings
264265
def YoptEmptyLineNumbers = Yopt.contains(YoptChoices.emptyLineNumbers)
265266
def YoptEmptyLabels = Yopt.contains(YoptChoices.emptyLabels)
266267
def YoptCompactLocals = Yopt.contains(YoptChoices.compactLocals)
268+
def YoptNullnessTracking = Yopt.contains(YoptChoices.nullnessTracking)
267269

268270
def YoptInlineProject = Yopt.contains(YoptChoices.inlineProject)
269271
def YoptInlineGlobal = Yopt.contains(YoptChoices.inlineGlobal)

0 commit comments

Comments
 (0)