@@ -145,115 +145,355 @@ class InlineBytecodeTests extends DottyBytecodeTest {
145
145
LineNumber (3 , Label (0 )),
146
146
VarOp (ALOAD , 0 ),
147
147
Ldc (LDC , " track" ),
148
+ Label (5 ),
149
+ LineNumber (18 , Label (5 )),
148
150
Op (ICONST_0 ),
151
+ // TODO missing LineNumber(3, ...) and other below. It look like we do not emmit the position
152
+ // of the invocation, instead we use the position of the last parameter (see `@Test def i4947a2`)
149
153
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
150
- Label (7 ),
151
- LineNumber (4 , Label (7 )),
154
+ Label (9 ),
155
+ LineNumber (4 , Label (9 )),
152
156
VarOp (ALOAD , 0 ),
153
157
Ldc (LDC , " track" ),
158
+ Label (13 ),
159
+ LineNumber (18 , Label (13 )),
154
160
Op (ICONST_0 ),
155
161
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
156
- Label (13 ),
157
- LineNumber (3 , Label (13 )),
162
+ Label (17 ),
163
+ LineNumber (3 , Label (17 )),
158
164
VarOp (ALOAD , 0 ),
159
165
Ldc (LDC , " track" ),
166
+ Label (21 ),
167
+ LineNumber (19 , Label (21 )),
160
168
Op (ICONST_2 ),
161
169
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
162
- Label (19 ),
163
- LineNumber (4 , Label (19 )),
170
+ Label (25 ),
171
+ LineNumber (4 , Label (25 )),
164
172
VarOp (ALOAD , 0 ),
165
173
Ldc (LDC , " track" ),
174
+ Label (29 ),
175
+ LineNumber (19 , Label (29 )),
166
176
Op (ICONST_2 ),
167
177
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
168
- Label (25 ),
169
- LineNumber (20 , Label (25 )),
178
+ Label (33 ),
179
+ LineNumber (20 , Label (33 )),
170
180
VarOp (ALOAD , 0 ),
171
181
Ldc (LDC , " main1" ),
172
182
Op (ICONST_M1 ),
173
183
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
174
- Label (31 ),
175
- LineNumber (21 , Label (31 )),
184
+ Label (39 ),
185
+ LineNumber (21 , Label (39 )),
176
186
VarOp (ALOAD , 0 ),
177
187
Ldc (LDC , " main2" ),
178
188
Op (ICONST_M1 ),
179
189
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
180
- Label (37 ),
181
- LineNumber (9 , Label (37 )),
190
+ Label (45 ),
191
+ LineNumber (19 , Label (45 )),
182
192
Op (ICONST_2 ),
183
- Label (40 ),
184
- LineNumber (3 , Label (40 )),
193
+ Label (48 ),
194
+ LineNumber (3 , Label (48 )),
185
195
VarOp (ALOAD , 0 ),
186
196
Ldc (LDC , " track" ),
197
+ Label (52 ),
198
+ LineNumber (9 , Label (52 )),
187
199
Op (ICONST_1 ),
188
200
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
189
- Label (46 ),
190
- LineNumber (4 , Label (46 )),
201
+ Label (56 ),
202
+ LineNumber (4 , Label (56 )),
191
203
VarOp (ALOAD , 0 ),
192
204
Ldc (LDC , " track" ),
205
+ Label (60 ),
206
+ LineNumber (9 , Label (60 )),
193
207
Op (ICONST_1 ),
194
208
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
195
- Label (52 ),
196
- LineNumber (20 , Label (52 )),
209
+ Label (64 ),
210
+ LineNumber (20 , Label (64 )),
197
211
VarOp (ALOAD , 0 ),
198
212
Ldc (LDC , " main1" ),
199
213
Op (ICONST_M1 ),
200
214
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
201
- Label (58 ),
202
- LineNumber (21 , Label (58 )),
215
+ Label (70 ),
216
+ LineNumber (21 , Label (70 )),
203
217
VarOp (ALOAD , 0 ),
204
218
Ldc (LDC , " main2" ),
205
219
Op (ICONST_M1 ),
206
220
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
207
- Label (64 ),
208
- LineNumber (9 , Label (64 )),
221
+ Label (76 ),
222
+ LineNumber (9 , Label (76 )),
209
223
Op (ICONST_1 ),
210
- Label (67 ),
211
- LineNumber (3 , Label (67 )),
224
+ Label (79 ),
225
+ LineNumber (3 , Label (79 )),
212
226
VarOp (ALOAD , 0 ),
213
227
Ldc (LDC , " track" ),
228
+ Label (83 ),
229
+ LineNumber (9 , Label (83 )),
214
230
Op (ICONST_0 ),
215
231
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
216
- Label (73 ),
217
- LineNumber (4 , Label (73 )),
232
+ Label (87 ),
233
+ LineNumber (4 , Label (87 )),
218
234
VarOp (ALOAD , 0 ),
219
235
Ldc (LDC , " track" ),
236
+ Label (91 ),
237
+ LineNumber (9 , Label (91 )),
220
238
Op (ICONST_0 ),
221
239
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
222
- Label (79 ),
223
- LineNumber (20 , Label (79 )),
240
+ Label (95 ),
241
+ LineNumber (20 , Label (95 )),
224
242
VarOp (ALOAD , 0 ),
225
243
Ldc (LDC , " main1" ),
226
244
Op (ICONST_M1 ),
227
245
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
228
- Label (85 ),
229
- LineNumber (21 , Label (85 )),
246
+ Label (101 ),
247
+ LineNumber (21 , Label (101 )),
230
248
VarOp (ALOAD , 0 ),
231
249
Ldc (LDC , " main2" ),
232
250
Op (ICONST_M1 ),
233
251
Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (Ljava/lang/String;I)V" , false ),
252
+ Label (107 ),
253
+ LineNumber (7 , Label (107 )),
254
+ Op (ICONST_1 ),
255
+ Op (IMUL ),
256
+ Label (111 ),
257
+ LineNumber (9 , Label (111 )),
258
+ Op (IMUL ),
259
+ Op (POP ),
260
+ Label (115 ),
261
+ LineNumber (7 , Label (115 )),
262
+ Op (ICONST_1 ),
263
+ Op (POP ),
264
+ Label (119 ),
265
+ LineNumber (23 , Label (119 )),
266
+ Op (RETURN ),
267
+ Label (122 )
268
+ )
269
+ assert(instructions == expected,
270
+ " `track` was not properly inlined in `main`\n " + diffInstructions(instructions, expected))
271
+
272
+ }
273
+ }
274
+
275
+ @ Test def i4947a2 = {
276
+ val source = """ class Foo {
277
+ | inline def fact[T](inline i: Int)(f: => T): Int = {
278
+ | printStack(i, "track") // line 3
279
+ | printStack(i, "track") // line 4
280
+ | f
281
+ | if (i == 0)
282
+ | 1 // line 7
283
+ | else {
284
+ | i * fact(i-1)(f) // line 9
285
+ | }
286
+ | }
287
+ |
288
+ | def printStack(i: Int, tag: String): Unit = { // line 13
289
+ | println(s"$tag (i = $i): ${new Exception().getStackTrace().apply(1)}") // line 14
290
+ | }
291
+ |
292
+ | def main(args: Array[String]): Unit = {
293
+ | fact(0) { // line 18
294
+ | fact(2) { // line 19
295
+ | printStack(-1, "main1") // line 20
296
+ | printStack(-1, "main2") // line 21
297
+ | }
298
+ | } // line 23
299
+ | }
300
+ |}
301
+ """ .stripMargin
302
+
303
+ checkBCode(source) { dir =>
304
+ val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
305
+ val clsNode = loadClassNode(clsIn, skipDebugInfo = false )
306
+
307
+ val track = clsNode.methods.asScala.find(_.name == " fact" )
308
+ assert(track.isEmpty, " method `fact` should have been erased" )
309
+
310
+ val main = getMethod(clsNode, " main" )
311
+ val instructions = instructionsFromMethod(main)
312
+ val expected =
313
+ List (
314
+ Label (0 ),
315
+ LineNumber (17 , Label (0 )),
316
+ LineNumber (3 , Label (0 )),
317
+ VarOp (ALOAD , 0 ),
318
+ Label (4 ),
319
+ LineNumber (18 , Label (4 )),
320
+ Op (ICONST_0 ),
321
+ Label (7 ),
322
+ LineNumber (3 , Label (7 )),
323
+ Ldc (LDC , " track" ),
324
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
325
+ Label (11 ),
326
+ LineNumber (4 , Label (11 )),
327
+ VarOp (ALOAD , 0 ),
328
+ Label (14 ),
329
+ LineNumber (18 , Label (14 )),
330
+ Op (ICONST_0 ),
331
+ Label (17 ),
332
+ LineNumber (4 , Label (17 )),
333
+ Ldc (LDC , " track" ),
334
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
335
+ Label (21 ),
336
+ LineNumber (3 , Label (21 )),
337
+ VarOp (ALOAD , 0 ),
338
+ Label (24 ),
339
+ LineNumber (19 , Label (24 )),
340
+ Op (ICONST_2 ),
341
+ Label (27 ),
342
+ LineNumber (3 , Label (27 )),
343
+ Ldc (LDC , " track" ),
344
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
345
+ Label (31 ),
346
+ LineNumber (4 , Label (31 )),
347
+ VarOp (ALOAD , 0 ),
348
+ Label (34 ),
349
+ LineNumber (19 , Label (34 )),
350
+ Op (ICONST_2 ),
351
+ Label (37 ),
352
+ LineNumber (4 , Label (37 )),
353
+ Ldc (LDC , " track" ),
354
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
355
+ Label (41 ),
356
+ LineNumber (20 , Label (41 )),
357
+ VarOp (ALOAD , 0 ),
358
+ Op (ICONST_M1 ),
359
+ Ldc (LDC , " main1" ),
360
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
361
+ Label (47 ),
362
+ LineNumber (21 , Label (47 )),
363
+ VarOp (ALOAD , 0 ),
364
+ Op (ICONST_M1 ),
365
+ Ldc (LDC , " main2" ),
366
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
367
+ Label (53 ),
368
+ LineNumber (19 , Label (53 )),
369
+ Op (ICONST_2 ),
370
+ Label (56 ),
371
+ LineNumber (3 , Label (56 )),
372
+ VarOp (ALOAD , 0 ),
373
+ Label (59 ),
374
+ LineNumber (9 , Label (59 )),
375
+ Op (ICONST_1 ),
376
+ Label (62 ),
377
+ LineNumber (3 , Label (62 )),
378
+ Ldc (LDC , " track" ),
379
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
380
+ Label (66 ),
381
+ LineNumber (4 , Label (66 )),
382
+ VarOp (ALOAD , 0 ),
383
+ Label (69 ),
384
+ LineNumber (9 , Label (69 )),
385
+ Op (ICONST_1 ),
386
+ Label (72 ),
387
+ LineNumber (4 , Label (72 )),
388
+ Ldc (LDC , " track" ),
389
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
390
+ Label (76 ),
391
+ LineNumber (20 , Label (76 )),
392
+ VarOp (ALOAD , 0 ),
393
+ Op (ICONST_M1 ),
394
+ Ldc (LDC , " main1" ),
395
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
396
+ Label (82 ),
397
+ LineNumber (21 , Label (82 )),
398
+ VarOp (ALOAD , 0 ),
399
+ Op (ICONST_M1 ),
400
+ Ldc (LDC , " main2" ),
401
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
402
+ Label (88 ),
403
+ LineNumber (9 , Label (88 )),
404
+ Op (ICONST_1 ),
234
405
Label (91 ),
235
- LineNumber (7 , Label (91 )),
406
+ LineNumber (3 , Label (91 )),
407
+ VarOp (ALOAD , 0 ),
408
+ Label (94 ),
409
+ LineNumber (9 , Label (94 )),
410
+ Op (ICONST_0 ),
411
+ Label (97 ),
412
+ LineNumber (3 , Label (97 )),
413
+ Ldc (LDC , " track" ),
414
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
415
+ Label (101 ),
416
+ LineNumber (4 , Label (101 )),
417
+ VarOp (ALOAD , 0 ),
418
+ Label (104 ),
419
+ LineNumber (9 , Label (104 )),
420
+ Op (ICONST_0 ),
421
+ Label (107 ),
422
+ LineNumber (4 , Label (107 )),
423
+ Ldc (LDC , " track" ),
424
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
425
+ Label (111 ),
426
+ LineNumber (20 , Label (111 )),
427
+ VarOp (ALOAD , 0 ),
428
+ Op (ICONST_M1 ),
429
+ Ldc (LDC , " main1" ),
430
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
431
+ Label (117 ),
432
+ LineNumber (21 , Label (117 )),
433
+ VarOp (ALOAD , 0 ),
434
+ Op (ICONST_M1 ),
435
+ Ldc (LDC , " main2" ),
436
+ Invoke (INVOKEVIRTUAL , " Foo" , " printStack" , " (ILjava/lang/String;)V" , false ),
437
+ Label (123 ),
438
+ LineNumber (7 , Label (123 )),
236
439
Op (ICONST_1 ),
237
440
Op (IMUL ),
238
- Label (95 ),
239
- LineNumber (9 , Label (95 )),
441
+ Label (127 ),
442
+ LineNumber (9 , Label (127 )),
240
443
Op (IMUL ),
241
444
Op (POP ),
242
- Label (99 ),
243
- LineNumber (7 , Label (99 )),
445
+ Label (131 ),
446
+ LineNumber (7 , Label (131 )),
244
447
Op (ICONST_1 ),
245
448
Op (POP ),
246
- Label (103 ),
247
- LineNumber (23 , Label (103 )),
449
+ Label (135 ),
450
+ LineNumber (23 , Label (135 )),
248
451
Op (RETURN ),
249
- Label (106 )
452
+ Label (138 )
250
453
)
251
454
assert(instructions == expected,
252
455
" `track` was not properly inlined in `main`\n " + diffInstructions(instructions, expected))
253
456
254
457
}
255
458
}
256
459
460
+ // @Test def i4947a3 = {
461
+ // val source = """class Foo {
462
+ // | inline def fun(tag: String): Unit = {
463
+ // | printStack( // line 3
464
+ // | tag // line 4
465
+ // | )
466
+ // | }
467
+ // |
468
+ // | def printStack(tag: String): Unit = { // line 8
469
+ // | println(s"$tag: ${new Exception().getStackTrace().apply(1)}") // line 9
470
+ // | }
471
+ // |
472
+ // | def main(args: Array[String]): Unit = { // line 12
473
+ // | fun("track") // line 13
474
+ // | }
475
+ // |}
476
+ // """.stripMargin
477
+ //
478
+ // checkBCode(source) { dir =>
479
+ // val clsIn = dir.lookupName("Foo.class", directory = false).input
480
+ // val clsNode = loadClassNode(clsIn, skipDebugInfo = false)
481
+ //
482
+ // val track = clsNode.methods.asScala.find(_.name == "fact")
483
+ // assert(track.isEmpty, "method `fact` should have been erased")
484
+ //
485
+ // val main = getMethod(clsNode, "main")
486
+ // val instructions = instructionsFromMethod(main)
487
+ // val expected =
488
+ // List(
489
+ //
490
+ // )
491
+ // assert(instructions == expected,
492
+ // "`track` was not properly inlined in `main`\n" + diffInstructions(instructions, expected))
493
+ //
494
+ // }
495
+ // }
496
+
257
497
@ Test def i4947b = {
258
498
val source = """ class Foo {
259
499
| inline def track2[T](f: => T) <: T = {
0 commit comments