Skip to content

Commit 7773e17

Browse files
committed
Remove uses of unsafeNulls from the JVM backend
1 parent c75cbbd commit 7773e17

11 files changed

Lines changed: 101 additions & 135 deletions

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dotty.tools
22
package backend
33
package jvm
44

5-
import scala.language.unsafeNulls
65
import scala.annotation.{switch, tailrec}
76
import scala.collection.mutable.SortedMap
87
import scala.tools.asm
@@ -202,7 +201,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
202201

203202
if (isArrayGet(code)) {
204203
// load argument on stack
205-
assert(args.length == 1, s"Too many arguments for array get operation: $tree");
204+
assert(args.length == 1, s"Too many arguments for array get operation: $tree")
206205
stack.push(k)
207206
genLoad(args.head, INT)
208207
stack.pop()
@@ -335,7 +334,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
335334
bc.store(idx, tk)
336335
val localVarStart = currProgramPoint()
337336
if (!isSynth) { // there are case <synthetic> ValDef's emitted by patmat
338-
varsInScope ::= (sym -> localVarStart)
337+
varsInScope = (sym -> localVarStart) :: varsInScope.nn
339338
}
340339
generatedType = UNIT
341340

@@ -547,7 +546,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
547546
private def fieldOp(field: Symbol, isLoad: Boolean, specificReceiver: Symbol | Null)(using Context): Unit = {
548547
val useSpecificReceiver = specificReceiver != null && !field.isScalaStatic
549548

550-
val owner = bTypeLoader.classBTypeFromSymbol(if (useSpecificReceiver) specificReceiver else field.owner).internalName
549+
val owner = bTypeLoader.classBTypeFromSymbol(if (useSpecificReceiver) specificReceiver.nn else field.owner).internalName
551550
val fieldJName = field.javaSimpleName
552551
val fieldDescr = symInfoTK(field).descriptor
553552
val isStatic = field.isStaticMember
@@ -653,7 +652,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
653652
if (earlyReturnVar == null) {
654653
earlyReturnVar = locals.makeLocal(returnType, "earlyReturnVar", expr.tpe, expr.span)
655654
}
656-
locals.store(earlyReturnVar)
655+
locals.store(earlyReturnVar.nn)
657656
}
658657
bc.goTo(nextCleanup)
659658
shouldEmitCleanup = true
@@ -986,7 +985,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
986985

987986
var flatKeys: List[Int] = Nil
988987
var targets: List[asm.Label] = Nil
989-
var default: asm.Label = null
988+
var default: asm.Label | Null = null
990989
var switchBlocks: List[(asm.Label, Tree)] = Nil
991990

992991
genLoad(selector, INT)
@@ -1020,7 +1019,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
10201019
if !hasDefault then
10211020
default = new asm.Label
10221021

1023-
bc.emitSWITCH(mkArrayReverse(flatKeys), mkArrayL(targets.reverse), default, MIN_SWITCH_DENSITY)
1022+
bc.emitSWITCH(mkArrayReverse(flatKeys), mkArrayL(targets.reverse), default.nn, MIN_SWITCH_DENSITY)
10241023

10251024
// emit switch-blocks.
10261025
for (sb <- switchBlocks.reverse) {
@@ -1030,7 +1029,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
10301029
}
10311030

10321031
if !hasDefault then
1033-
markProgramPoint(default)
1032+
markProgramPoint(default.nn)
10341033
emitThrowMatchError()
10351034
} else {
10361035

@@ -1042,13 +1041,12 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
10421041
* This mirrors the way that Java compiles `switch` on Strings.
10431042
*/
10441043

1045-
var default: asm.Label = null
1046-
var indirectBlocks: List[(asm.Label, Tree)] = Nil
1044+
var default: asm.Label | Null = null
1045+
var indirectBlocks: List[(asm.Label, Tree | Null)] = Nil
10471046

10481047

10491048
// Cases grouped by their hashCode
10501049
val casesByHash = SortedMap.empty[Int, List[(String, Either[asm.Label, Tree])]]
1051-
var caseFallback: Tree = null
10521050

10531051
for (caze @ CaseDef(pat, guard, body) <- cases) {
10541052
assert(guard == tpd.EmptyTree, guard)
@@ -1062,7 +1060,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
10621060
case Ident(nme.WILDCARD) =>
10631061
assert(default == null, s"multiple default targets in a Match node, at ${tree.span}")
10641062
default = new asm.Label
1065-
indirectBlocks ::= (default, body)
1063+
indirectBlocks ::= (default.nn, body)
10661064
case Alternative(alts) =>
10671065
// We need an extra basic block since multiple strings can lead to this code
10681066
val indirectCaseGroupLabel = new asm.Label
@@ -1097,7 +1095,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
10971095
val hasDefault = default != null
10981096
if !hasDefault then
10991097
default = new asm.Label
1100-
indirectBlocks ::= (default, null)
1098+
indirectBlocks ::= (default.nn, null)
11011099

11021100
// Push the hashCode of the string (or `0` it is `null`) onto the stack and switch on it
11031101
genLoadIfTo(
@@ -1109,7 +1107,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
11091107
INT,
11101108
LoadDestination.FallThrough
11111109
)
1112-
bc.emitSWITCH(mkArrayReverse(flatKeys), mkArrayL(targets.reverse), default, MIN_SWITCH_DENSITY)
1110+
bc.emitSWITCH(mkArrayReverse(flatKeys), mkArrayL(targets.reverse), default.nn, MIN_SWITCH_DENSITY)
11131111

11141112
// emit blocks for each hash case
11151113
for ((hashLabel, caseAlternatives) <- hashBlocks.reverse) {
@@ -1130,7 +1128,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
11301128
}
11311129
markProgramPoint(keepGoing)
11321130
}
1133-
bc.goTo(default)
1131+
bc.goTo(default.nn)
11341132
}
11351133

11361134
// emit blocks for common patterns
@@ -1165,7 +1163,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
11651163
def emitLocalVarScopes(): Unit =
11661164
if (BackendUtils.emitVars) {
11671165
val end = currProgramPoint()
1168-
for ((sym, start) <- varsInScope.reverse) {
1166+
for ((sym, start) <- varsInScope.nn.reverse) {
11691167
emitLocalVarScope(sym, start, end)
11701168
}
11711169
}
@@ -1445,7 +1443,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
14451443
assert(style.isVirtual || style.isSuper || specificReceiver == methodOwner, s"specificReceiver can only be specified for virtual and super calls. $method - $specificReceiver")
14461444

14471445
val useSpecificReceiver = specificReceiver != null && !defn.isBottomClass(specificReceiver) && !method.isScalaStatic
1448-
val receiver = if (useSpecificReceiver) specificReceiver else methodOwner
1446+
val receiver: Symbol = if (useSpecificReceiver) specificReceiver.nn else methodOwner
14491447

14501448
// TODO this JVM bug was resolved a very long time ago, workaround could be removed?
14511449
// workaround for a JVM bug: https://bugs.openjdk.java.net/browse/JDK-8154587
@@ -1603,7 +1601,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
16031601
case Literal(Constant(null)) => true
16041602
case _ => false
16051603
}
1606-
def ifOneIsNull(l: Tree, r: Tree): Tree = if (isNull(l)) r else if (isNull(r)) l else null
1604+
def ifOneIsNull(l: Tree, r: Tree): Tree | Null = if (isNull(l)) r else if (isNull(r)) l else null
16071605
val nonNullSide = if (ScalaPrimitivesOps.isReferenceEqualityOp(code)) ifOneIsNull(l, r) else null
16081606
if (nonNullSide != null) {
16091607
// special-case reference (in)equality test for null (null eq x, x eq null)

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dotty.tools
22
package backend
33
package jvm
44

5-
import scala.language.unsafeNulls
65
import scala.tools.asm
76
import scala.tools.asm.{AnnotationVisitor, ClassWriter, Opcodes}
87
import scala.collection.mutable
@@ -206,7 +205,7 @@ trait BCodeHelpers(val bTypeLoader: BTypeLoader, val bTypes: WellKnownBTypes) ex
206205
}
207206

208207
private def emitArgument(av: AnnotationVisitor,
209-
name: String,
208+
name: String | Null,
210209
arg: Tree)(using Context): Unit = {
211210
val narg = normalizeArgument(arg)
212211
// Transformation phases are not run on annotation trees, so we need to run
@@ -652,7 +651,7 @@ trait BCodeHelpers(val bTypeLoader: BTypeLoader, val bTypes: WellKnownBTypes) ex
652651
|| sym.is(Bridge)
653652
)
654653

655-
private def getStaticForwarderGenericSignature(sym: Symbol, moduleClass: Symbol)(using Context): String = {
654+
private def getStaticForwarderGenericSignature(sym: Symbol, moduleClass: Symbol)(using Context): String | Null = {
656655
// scala/bug#3452 Static forwarder generation uses the same erased signature as the method if forwards to.
657656
// By rights, it should use the signature as-seen-from the module class, and add suitable
658657
// primitive and value-class boxing/unboxing.

compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dotty.tools
22
package backend
33
package jvm
44

5-
import scala.language.unsafeNulls
65
import scala.tools.asm
76
import scala.annotation.switch
87
import scala.tools.asm.tree.MethodInsnNode

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dotty.tools
22
package backend
33
package jvm
44

5-
import scala.language.unsafeNulls
65
import scala.annotation.tailrec
76
import scala.collection.{immutable, mutable}
87
import scala.tools.asm
@@ -23,6 +22,8 @@ import SymbolUtils.given
2322
import dotty.tools.dotc.core.NameOps.isStaticConstructorName
2423
import tpd.*
2524

25+
import scala.compiletime.uninitialized
26+
2627
/*
2728
*
2829
* @author Miguel Garcia, http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
@@ -132,14 +133,14 @@ trait BCodeSkelBuilder extends BCodeHelpers {
132133
with BCJGenSigGen {
133134

134135
// Strangely I can't find this in the asm code 255, but reserving 1 for "this"
135-
inline val MaximumJvmParameters = 254
136+
private inline val MaximumJvmParameters = 254
136137

137138
// current class
138-
var cnode: ClassNode1 = null
139-
var thisName: String = null // the internal name of the class being emitted
139+
private var cnode: ClassNode1 = uninitialized
140+
private var thisName: String = uninitialized // the internal name of the class being emitted
140141

141-
var claszSymbol: Symbol = null
142-
var isCZStaticModule = false
142+
protected var claszSymbol: Symbol = uninitialized
143+
private var isCZStaticModule = false
143144

144145
// keep track of interfaces that are used in super calls, as they need to be directly inherited even if they are also indirectly inherited
145146
val superCallTargets = mutable.LinkedHashSet[ClassBType]()
@@ -160,7 +161,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
160161

161162
/* ---------------- helper utils for generating classes and fields ---------------- */
162163

163-
def genPlainClass(cd0: TypeDef)(using Context) = (cd0: @unchecked) match {
164+
def genPlainClass(cd0: TypeDef)(using Context): ClassNode1 = (cd0: @unchecked) match {
164165
case TypeDef(_, impl: Template) =>
165166
assert(cnode == null, "GenBCode detected nested methods.")
166167

@@ -288,7 +289,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
288289
TraceUtils.traceClassIfRequested(cnode)
289290

290291
assert(cd.symbol == claszSymbol, "Someone messed up BCodePhase.claszSymbol during genPlainClass().")
291-
292+
cnode
292293
} // end of method genPlainClass()
293294

294295
/*
@@ -386,7 +387,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
386387
.addFlagIf(!sym.is(Mutable), ACC_FINAL)
387388
}
388389

389-
def addClassField(f: Symbol)(using Context): Unit = {
390+
private def addClassField(f: Symbol)(using Context): Unit = {
390391
val javagensig = getGenericSignature(f, claszSymbol)
391392
val flags = javaFieldFlags(f)
392393

@@ -404,7 +405,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
404405
emitAnnotations(jfield, f.annotations)
405406
}
406407

407-
def addClassFields()(using Context): Unit =
408+
private def addClassFields()(using Context): Unit =
408409
/* Non-method term members are fields, except for module members. Module
409410
* members can only happen on .NET (no flatten) for inner traits. There,
410411
* a module symbol is generated (transformInfo in mixin) which is used
@@ -415,18 +416,18 @@ trait BCodeSkelBuilder extends BCodeHelpers {
415416
claszSymbol.info.decls.filter(p => p.isTerm && !p.is(Method)).foreach(addClassField)
416417

417418
// current method
418-
var mnode: MethodNode1 = null
419-
var jMethodName: String = null
420-
var isMethSymStaticCtor = false
421-
var returnType: BType = null
422-
var methSymbol: Symbol = null
419+
var mnode: MethodNode1 = uninitialized
420+
var jMethodName: String = uninitialized
421+
private var isMethSymStaticCtor = false
422+
var returnType: BType = uninitialized
423+
var methSymbol: Symbol = uninitialized
423424
// used by genLoadTry() and genSynchronized()
424-
var earlyReturnVar: Symbol = null
425+
var earlyReturnVar: Symbol | Null = null
425426
var shouldEmitCleanup = false
426427
// stack tracking
427428
val stack = new BTypesStack
428429
// line numbers
429-
var lastEmittedLineNr = -1
430+
private var lastEmittedLineNr = -1
430431

431432
object bc extends JCodeMethodN {
432433
override def jmethod = PlainSkelBuilder.this.mnode
@@ -439,7 +440,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
439440
* The `jumpDest` map is used to find the `LoadDestination` at the end of the `Labeled` block, as well as the
440441
* corresponding expected type. The `LoadDestination` can never be `FallThrough` here.
441442
*/
442-
var jumpDest: immutable.Map[ /* Labeled */ Symbol, (BType, LoadDestination) ] = null
443+
var jumpDest: immutable.Map[ /* Labeled */ Symbol, (BType, LoadDestination) ] = immutable.Map.empty
443444
def registerJumpDest(labelSym: Symbol, expectedType: BType, dest: LoadDestination)(using Context): Unit = {
444445
assert(labelSym.is(Label), s"trying to register a jump-dest for a non-label symbol, at: ${labelSym.span}")
445446
assert(dest != LoadDestination.FallThrough, s"trying to register a FallThrough dest for label, at: ${labelSym.span}")
@@ -483,10 +484,10 @@ trait BCodeSkelBuilder extends BCodeHelpers {
483484
* emitted for that purpose as described in `genLoadTry()` and `genSynchronized()`.
484485
*/
485486
var cleanups: List[asm.Label] = Nil
486-
def registerCleanup(finCleanup: asm.Label): Unit = {
487+
def registerCleanup(finCleanup: asm.Label | Null): Unit = {
487488
if (finCleanup != null) { cleanups = finCleanup :: cleanups }
488489
}
489-
def unregisterCleanup(finCleanup: asm.Label): Unit = {
490+
def unregisterCleanup(finCleanup: asm.Label | Null): Unit = {
490491
if (finCleanup != null) {
491492
assert(cleanups.head eq finCleanup,
492493
s"Bad nesting of cleanup operations: $cleanups trying to unregister: $finCleanup")
@@ -584,7 +585,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
584585
/* ---------------- Part 2 of program points, ie Labels in the ASM world ---------------- */
585586

586587
// bookkeeping the scopes of non-synthetic local vars, to emit debug info (`emitVars`).
587-
var varsInScope: List[(Symbol, asm.Label)] = null // (local-var-sym -> start-of-scope)
588+
var varsInScope: List[(Symbol, asm.Label)] | Null = null // (local-var-sym -> start-of-scope)
588589

589590
// helpers around program-points.
590591
def lastInsn: asm.tree.AbstractInsnNode = mnode.instructions.getLast
@@ -805,7 +806,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
805806
.withAttachment(BCodeHelpers.UseInvokeSpecial, ())
806807
})
807808

808-
def genDefDef(dd: DefDef)(using Context): Unit = {
809+
private def genDefDef(dd: DefDef)(using Context): Unit = {
809810
val rhs = dd.rhs
810811
val vparamss = dd.termParamss
811812
// the only method whose implementation is not emitted: getClass()
@@ -923,7 +924,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
923924

924925
TraceUtils.traceMethodIfRequested(mnode)
925926

926-
mnode = null
927+
mnode = null.asInstanceOf[MethodNode1] // for GC
927928
} // end of method genDefDef()
928929

929930
def emitLocalVarScope(sym: Symbol, start: asm.Label, end: asm.Label, force: Boolean = false): Unit = {

0 commit comments

Comments
 (0)