@@ -3,6 +3,10 @@ package dotty.tools.backend.jvm
3
3
import org .junit .Assert ._
4
4
import org .junit .Test
5
5
6
+ import scala .tools .asm .Opcodes ._
7
+
8
+ import scala .collection .JavaConverters ._
9
+
6
10
class InlineBytecodeTests extends DottyBytecodeTest {
7
11
import ASMConverters ._
8
12
@ Test def inlineUnit = {
@@ -37,4 +41,244 @@ class InlineBytecodeTests extends DottyBytecodeTest {
37
41
diffInstructions(instructions2, instructions3))
38
42
}
39
43
}
44
+
45
+ @ Test def i4947 = {
46
+ val source = """ class Foo {
47
+ | transparent def track[T](f: => T): T = {
48
+ | foo("tracking") // line 3
49
+ | f // line 4
50
+ | }
51
+ | def main(args: Array[String]): Unit = { // line 6
52
+ | track { // line 7
53
+ | foo("abc") // line 8
54
+ | track { // line 9
55
+ | foo("inner") // line 10
56
+ | }
57
+ | } // line 11
58
+ | }
59
+ | def foo(str: String): Unit = ()
60
+ |}
61
+ """ .stripMargin
62
+
63
+ checkBCode(source) { dir =>
64
+ val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
65
+ val clsNode = loadClassNode(clsIn, skipDebugInfo = false )
66
+
67
+ val track = clsNode.methods.asScala.find(_.name == " track" )
68
+ assert(track.isEmpty, " method `track` should have been erased" )
69
+
70
+ val main = getMethod(clsNode, " main" )
71
+ val instructions = instructionsFromMethod(main)
72
+ val expected =
73
+ List (
74
+ Label (0 ),
75
+ LineNumber (6 , Label (0 )),
76
+ LineNumber (3 , Label (0 )),
77
+ VarOp (ALOAD , 0 ),
78
+ Ldc (LDC , " tracking" ),
79
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
80
+ Label (6 ),
81
+ LineNumber (8 , Label (6 )),
82
+ VarOp (ALOAD , 0 ),
83
+ Ldc (LDC , " abc" ),
84
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
85
+ Label (11 ),
86
+ LineNumber (3 , Label (11 )),
87
+ VarOp (ALOAD , 0 ),
88
+ Ldc (LDC , " tracking" ),
89
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
90
+ Label (16 ),
91
+ LineNumber (10 , Label (16 )),
92
+ VarOp (ALOAD , 0 ),
93
+ Ldc (LDC , " inner" ),
94
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
95
+ Op (RETURN ),
96
+ Label (22 )
97
+ )
98
+ assert(instructions == expected,
99
+ " `track` was not properly inlined in `main`\n " + diffInstructions(instructions, expected))
100
+
101
+ }
102
+ }
103
+
104
+ @ Test def i4947b = {
105
+ val source = """ class Foo {
106
+ | transparent def track2[T](f: => T): T = {
107
+ | foo("tracking2") // line 3
108
+ | f // line 4
109
+ | }
110
+ | transparent def track[T](f: => T): T = {
111
+ | foo("tracking") // line 7
112
+ | track2 { // line 8
113
+ | f // line 9
114
+ | }
115
+ | }
116
+ | def main(args: Array[String]): Unit = { // line 12
117
+ | track { // line 13
118
+ | foo("abc") // line 14
119
+ | }
120
+ | }
121
+ | def foo(str: String): Unit = ()
122
+ |}
123
+ """ .stripMargin
124
+
125
+ checkBCode(source) { dir =>
126
+ val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
127
+ val clsNode = loadClassNode(clsIn, skipDebugInfo = false )
128
+
129
+ val track = clsNode.methods.asScala.find(_.name == " track" )
130
+ assert(track.isEmpty, " method `track` should have been erased" )
131
+
132
+ val track2 = clsNode.methods.asScala.find(_.name == " track2" )
133
+ assert(track2.isEmpty, " method `track2` should have been erased" )
134
+
135
+ val main = getMethod(clsNode, " main" )
136
+ val instructions = instructionsFromMethod(main)
137
+ val expected =
138
+ List (
139
+ Label (0 ),
140
+ LineNumber (12 , Label (0 )),
141
+ LineNumber (7 , Label (0 )),
142
+ VarOp (ALOAD , 0 ),
143
+ Ldc (LDC , " tracking" ),
144
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
145
+ Label (6 ),
146
+ LineNumber (3 , Label (6 )),
147
+ VarOp (ALOAD , 0 ),
148
+ Ldc (LDC , " tracking2" ),
149
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
150
+ Label (11 ),
151
+ LineNumber (14 , Label (11 )),
152
+ VarOp (ALOAD , 0 ),
153
+ Ldc (LDC , " abc" ),
154
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
155
+ Op (RETURN ),
156
+ Label (17 )
157
+ )
158
+ assert(instructions == expected,
159
+ " `track` was not properly inlined in `main`\n " + diffInstructions(instructions, expected))
160
+
161
+ }
162
+ }
163
+
164
+ @ Test def i4947c = {
165
+ val source = """ class Foo {
166
+ | transparent def track2[T](f: => T): T = {
167
+ | foo("tracking2") // line 3
168
+ | f // line 4
169
+ | }
170
+ | transparent def track[T](f: => T): T = {
171
+ | track2 { // line 7
172
+ | foo("fgh") // line 8
173
+ | f // line 9
174
+ | }
175
+ | }
176
+ | def main(args: Array[String]): Unit = { // line 12
177
+ | track { // line 13
178
+ | foo("abc") // line 14
179
+ | }
180
+ | }
181
+ | def foo(str: String): Unit = ()
182
+ |}
183
+ """ .stripMargin
184
+
185
+ checkBCode(source) { dir =>
186
+ val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
187
+ val clsNode = loadClassNode(clsIn, skipDebugInfo = false )
188
+
189
+ val track = clsNode.methods.asScala.find(_.name == " track" )
190
+ assert(track.isEmpty, " method `track` should have been erased" )
191
+
192
+ val track2 = clsNode.methods.asScala.find(_.name == " track2" )
193
+ assert(track2.isEmpty, " method `track2` should have been erased" )
194
+
195
+ val main = getMethod(clsNode, " main" )
196
+ val instructions = instructionsFromMethod(main)
197
+ val expected =
198
+ List (
199
+ Label (0 ),
200
+ LineNumber (12 , Label (0 )),
201
+ LineNumber (3 , Label (0 )),
202
+ VarOp (ALOAD , 0 ),
203
+ Ldc (LDC , " tracking2" ),
204
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
205
+ Label (6 ),
206
+ LineNumber (8 , Label (6 )),
207
+ VarOp (ALOAD , 0 ),
208
+ Ldc (LDC , " fgh" ),
209
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
210
+ Label (11 ),
211
+ LineNumber (14 , Label (11 )),
212
+ VarOp (ALOAD , 0 ),
213
+ Ldc (LDC , " abc" ),
214
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
215
+ Op (RETURN ),
216
+ Label (17 )
217
+ )
218
+ assert(instructions == expected,
219
+ " `track` was not properly inlined in `main`\n " + diffInstructions(instructions, expected))
220
+
221
+ }
222
+ }
223
+
224
+ @ Test def i4947d = {
225
+ val source = """ class Foo {
226
+ | transparent def track2[T](f: => T): T = {
227
+ | foo("tracking2") // line 3
228
+ | f // line 4
229
+ | }
230
+ | transparent def track[T](f: => T): T = {
231
+ | track2 { // line 7
232
+ | track2 { // line 8
233
+ | f // line 9
234
+ | }
235
+ | }
236
+ | }
237
+ | def main(args: Array[String]): Unit = { // line 13
238
+ | track { // line 14
239
+ | foo("abc") // line 15
240
+ | }
241
+ | }
242
+ | def foo(str: String): Unit = ()
243
+ |}
244
+ """ .stripMargin
245
+
246
+ checkBCode(source) { dir =>
247
+ val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
248
+ val clsNode = loadClassNode(clsIn, skipDebugInfo = false )
249
+
250
+ val track = clsNode.methods.asScala.find(_.name == " track" )
251
+ assert(track.isEmpty, " method `track` should have been erased" )
252
+
253
+ val track2 = clsNode.methods.asScala.find(_.name == " track2" )
254
+ assert(track2.isEmpty, " method `track2` should have been erased" )
255
+
256
+ val main = getMethod(clsNode, " main" )
257
+ val instructions = instructionsFromMethod(main)
258
+ val expected =
259
+ List (
260
+ Label (0 ),
261
+ LineNumber (13 , Label (0 )),
262
+ LineNumber (3 , Label (0 )),
263
+ VarOp (ALOAD , 0 ),
264
+ Ldc (LDC , " tracking2" ),
265
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
266
+ Label (6 ),
267
+ LineNumber (3 , Label (6 )),
268
+ VarOp (ALOAD , 0 ),
269
+ Ldc (LDC , " tracking2" ),
270
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
271
+ Label (11 ),
272
+ LineNumber (15 , Label (11 )),
273
+ VarOp (ALOAD , 0 ),
274
+ Ldc (LDC , " abc" ),
275
+ Invoke (INVOKEVIRTUAL , " Foo" , " foo" , " (Ljava/lang/String;)V" , false ),
276
+ Op (RETURN ),
277
+ Label (17 )
278
+ )
279
+ assert(instructions == expected,
280
+ " `track` was not properly inlined in `main`\n " + diffInstructions(instructions, expected))
281
+
282
+ }
283
+ }
40
284
}
0 commit comments