@@ -3,6 +3,10 @@ package dotty.tools.backend.jvm
33import  org .junit .Assert ._ 
44import  org .junit .Test 
55
6+ import  scala .tools .asm .Opcodes ._ 
7+ 
8+ import  scala .collection .JavaConverters ._ 
9+ 
610class  InlineBytecodeTests  extends  DottyBytecodeTest  {
711  import  ASMConverters ._ 
812  @ Test  def  inlineUnit  =  {
@@ -37,4 +41,244 @@ class InlineBytecodeTests extends DottyBytecodeTest {
3741        diffInstructions(instructions2, instructions3))
3842    }
3943  }
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" =  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" =  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" =  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" =  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+   }
40284}
0 commit comments