@@ -208,4 +208,52 @@ class UnreachableCodeTest {
208
208
assertTrue(List (FrameEntry (F_FULL , List (INTEGER , DOUBLE , Label (3 )), List (" java/lang/Object" , Label (4 ))), Label (3 ), Label (4 )) ===
209
209
List (FrameEntry (F_FULL , List (INTEGER , DOUBLE , Label (1 )), List (" java/lang/Object" , Label (3 ))), Label (1 ), Label (3 )))
210
210
}
211
+
212
+ @ Test
213
+ def loadNullNothingBytecode (): Unit = {
214
+ val code =
215
+ """ class C {
216
+ | def nl: Null = null
217
+ | def nt: Nothing = throw new Error("")
218
+ | def cons(a: Any) = ()
219
+ |
220
+ | def t1 = cons(null)
221
+ | def t2 = cons(nl)
222
+ | def t3 = cons(throw new Error(""))
223
+ | def t4 = cons(nt)
224
+ |}
225
+ """ .stripMargin
226
+ val List (c) = compileClasses(noOptCompiler)(code)
227
+
228
+ assertEquals(getSingleMethod(c, " nl" ).instructions.summary, List (ACONST_NULL , ARETURN ))
229
+
230
+ assertEquals(getSingleMethod(c, " nt" ).instructions.summary, List (
231
+ NEW , DUP , LDC , " <init>" , ATHROW ))
232
+
233
+ assertEquals(getSingleMethod(c, " t1" ).instructions.summary, List (
234
+ ALOAD , ACONST_NULL , " cons" , RETURN ))
235
+
236
+ // GenBCode introduces POP; ACONST_NULL after loading an expression of type scala.runtime.Null$,
237
+ // see comment in BCodeBodyBuilder.adapt
238
+ assertEquals(getSingleMethod(c, " t2" ).instructions.summary, List (
239
+ ALOAD , ALOAD , " nl" , POP , ACONST_NULL , " cons" , RETURN ))
240
+
241
+ // the bytecode generated by GenBCode is ... ATHROW; INVOKEVIRTUAL C.cons; RETURN
242
+ // the ASM classfile writer creates a new basic block (creates a label) right after the ATHROW
243
+ // and replaces all instructions by NOP*; ATHROW, see comment in BCodeBodyBuilder.adapt
244
+ // NOTE: DCE is enabled by default and gets rid of the redundant code (tested below)
245
+ assertEquals(getSingleMethod(c, " t3" ).instructions.summary, List (
246
+ ALOAD , NEW , DUP , LDC , " <init>" , ATHROW , NOP , NOP , NOP , ATHROW ))
247
+
248
+ // GenBCode introduces an ATHROW after the invocation of C.nt, see BCodeBodyBuilder.adapt
249
+ // NOTE: DCE is enabled by default and gets rid of the redundant code (tested below)
250
+ assertEquals(getSingleMethod(c, " t4" ).instructions.summary, List (
251
+ ALOAD , ALOAD , " nt" , ATHROW , NOP , NOP , NOP , ATHROW ))
252
+
253
+ val List (cDCE) = compileClasses(dceCompiler)(code)
254
+ assertEquals(getSingleMethod(cDCE, " t3" ).instructions.summary, List (
255
+ ALOAD , NEW , DUP , LDC , " <init>" , ATHROW ))
256
+ assertEquals(getSingleMethod(cDCE, " t4" ).instructions.summary, List (
257
+ ALOAD , ALOAD , " nt" , ATHROW ))
258
+ }
211
259
}
0 commit comments