@@ -101,6 +101,159 @@ class InlineBytecodeTests extends DottyBytecodeTest {
101
101
}
102
102
}
103
103
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
+
104
257
@ Test def i4947b = {
105
258
val source = """ class Foo {
106
259
| inline def track2[T](f: => T) <: T = {
0 commit comments