Skip to content

Commit ea0e862

Browse files
committed
Add previous bytecode lines check
1 parent 11de15d commit ea0e862

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,159 @@ class InlineBytecodeTests extends DottyBytecodeTest {
101101
}
102102
}
103103

104+
@Test def i4947a = {
105+
val source = """class Foo {
106+
| inline def fact[T](inline i: Int)(f: => T): Int = {
107+
| printStack("track", i) // line 3
108+
| printStack("track", i) // line 4
109+
| f
110+
| if (i == 0)
111+
| 1 // line 7
112+
| else {
113+
| i * fact(i-1)(f) // line 9
114+
| }
115+
| }
116+
|
117+
| def printStack(tag: String, i: Int): Unit = { // line 13
118+
| println(s"$tag (i = $i): ${new Exception().getStackTrace().apply(1)}") // line 14
119+
| }
120+
|
121+
| def main(args: Array[String]): Unit = {
122+
| fact(0) { // line 18
123+
| fact(2) { // line 19
124+
| printStack("main1", -1) // line 20
125+
| printStack("main2", -1) // line 21
126+
| }
127+
| } // line 23
128+
| }
129+
|}
130+
""".stripMargin
131+
132+
checkBCode(source) { dir =>
133+
val clsIn = dir.lookupName("Foo.class", directory = false).input
134+
val clsNode = loadClassNode(clsIn, skipDebugInfo = false)
135+
136+
val track = clsNode.methods.asScala.find(_.name == "fact")
137+
assert(track.isEmpty, "method `fact` should have been erased")
138+
139+
val main = getMethod(clsNode, "main")
140+
val instructions = instructionsFromMethod(main)
141+
val expected =
142+
List(
143+
Label(0),
144+
LineNumber(17, Label(0)),
145+
LineNumber(3, Label(0)),
146+
VarOp(ALOAD, 0),
147+
Ldc(LDC, "track"),
148+
Op(ICONST_0),
149+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
150+
Label(7),
151+
LineNumber(4, Label(7)),
152+
VarOp(ALOAD, 0),
153+
Ldc(LDC, "track"),
154+
Op(ICONST_0),
155+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
156+
Label(13),
157+
LineNumber(3, Label(13)),
158+
VarOp(ALOAD, 0),
159+
Ldc(LDC, "track"),
160+
Op(ICONST_2),
161+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
162+
Label(19),
163+
LineNumber(4, Label(19)),
164+
VarOp(ALOAD, 0),
165+
Ldc(LDC, "track"),
166+
Op(ICONST_2),
167+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
168+
Label(25),
169+
LineNumber(20, Label(25)),
170+
VarOp(ALOAD, 0),
171+
Ldc(LDC, "main1"),
172+
Op(ICONST_M1),
173+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
174+
Label(31),
175+
LineNumber(21, Label(31)),
176+
VarOp(ALOAD, 0),
177+
Ldc(LDC, "main2"),
178+
Op(ICONST_M1),
179+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
180+
Label(37),
181+
LineNumber(9, Label(37)),
182+
Op(ICONST_2),
183+
Label(40),
184+
LineNumber(3, Label(40)),
185+
VarOp(ALOAD, 0),
186+
Ldc(LDC, "track"),
187+
Op(ICONST_1),
188+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
189+
Label(46),
190+
LineNumber(4, Label(46)),
191+
VarOp(ALOAD, 0),
192+
Ldc(LDC, "track"),
193+
Op(ICONST_1),
194+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
195+
Label(52),
196+
LineNumber(20, Label(52)),
197+
VarOp(ALOAD, 0),
198+
Ldc(LDC, "main1"),
199+
Op(ICONST_M1),
200+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
201+
Label(58),
202+
LineNumber(21, Label(58)),
203+
VarOp(ALOAD, 0),
204+
Ldc(LDC, "main2"),
205+
Op(ICONST_M1),
206+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
207+
Label(64),
208+
LineNumber(9, Label(64)),
209+
Op(ICONST_1),
210+
Label(67),
211+
LineNumber(3, Label(67)),
212+
VarOp(ALOAD, 0),
213+
Ldc(LDC, "track"),
214+
Op(ICONST_0),
215+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
216+
Label(73),
217+
LineNumber(4, Label(73)),
218+
VarOp(ALOAD, 0),
219+
Ldc(LDC, "track"),
220+
Op(ICONST_0),
221+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
222+
Label(79),
223+
LineNumber(20, Label(79)),
224+
VarOp(ALOAD, 0),
225+
Ldc(LDC, "main1"),
226+
Op(ICONST_M1),
227+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
228+
Label(85),
229+
LineNumber(21, Label(85)),
230+
VarOp(ALOAD, 0),
231+
Ldc(LDC, "main2"),
232+
Op(ICONST_M1),
233+
Invoke(INVOKEVIRTUAL, "Foo", "printStack", "(Ljava/lang/String;I)V", false),
234+
Label(91),
235+
LineNumber(7, Label(91)),
236+
Op(ICONST_1),
237+
Op(IMUL),
238+
Label(95),
239+
LineNumber(9, Label(95)),
240+
Op(IMUL),
241+
Op(POP),
242+
Label(99),
243+
LineNumber(7, Label(99)),
244+
Op(ICONST_1),
245+
Op(POP),
246+
Label(103),
247+
LineNumber(23, Label(103)),
248+
Op(RETURN),
249+
Label(106)
250+
)
251+
assert(instructions == expected,
252+
"`track` was not properly inlined in `main`\n" + diffInstructions(instructions, expected))
253+
254+
}
255+
}
256+
104257
@Test def i4947b = {
105258
val source = """class Foo {
106259
| inline def track2[T](f: => T) <: T = {

0 commit comments

Comments
 (0)