@@ -201,34 +201,108 @@ class ArrayApplyOptTest extends DottyBytecodeTest {
201201 """ .stripMargin
202202 }
203203
204- def checkApplyAvoidsIntermediateArray (name : String )(source : String ) = {
204+ @ Test def testListApplyAvoidsIntermediateArray_max1 = {
205+ checkApplyAvoidsIntermediateArray_examples(" max1" ):
206+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", "5", "6", "7")
207+ | def meth2: List[Object] = new ::("1", new ::("2", new ::("3", new ::("4", new ::("5", new ::("6", new ::("7", Nil)))))))
208+ """ .stripMargin
209+ }
210+
211+ @ Test def testListApplyAvoidsIntermediateArray_max2 = {
212+ checkApplyAvoidsIntermediateArray_examples(" max2" ):
213+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", "5", "6", List[Object]())
214+ | def meth2: List[Object] = new ::("1", new ::("2", new ::("3", new ::("4", new ::("5", new ::("6", new ::(Nil, Nil)))))))
215+ """ .stripMargin
216+ }
217+
218+ @ Test def testListApplyAvoidsIntermediateArray_max3 = {
219+ checkApplyAvoidsIntermediateArray_examples(" max3" ):
220+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", "5", List[Object]("6"))
221+ | def meth2: List[Object] = new ::("1", new ::("2", new ::("3", new ::("4", new ::("5", new ::(new ::("6", Nil), Nil))))))
222+ """ .stripMargin
223+ }
224+
225+ @ Test def testListApplyAvoidsIntermediateArray_max4 = {
226+ checkApplyAvoidsIntermediateArray_examples(" max4" ):
227+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", List[Object]("5", "6"))
228+ | def meth2: List[Object] = new ::("1", new ::("2", new ::("3", new ::("4", new ::(new ::("5", new ::("6", Nil)), Nil)))))
229+ """ .stripMargin
230+ }
231+
232+ @ Test def testListApplyAvoidsIntermediateArray_over1 = {
233+ checkApplyAvoidsIntermediateArray_examples(" over1" ):
234+ """ def meth1: List[Object] = List("1", "2", "3", "4", "5", "6", "7", "8")
235+ | def meth2: List[Object] = List(wrapRefArray(Array("1", "2", "3", "4", "5", "6", "7", "8"))*)
236+ """ .stripMargin
237+ }
238+
239+ @ Test def testListApplyAvoidsIntermediateArray_over2 = {
240+ checkApplyAvoidsIntermediateArray_examples(" over2" ):
241+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", "5", "6", "7", List[Object]())
242+ | def meth2: List[Object] = List(wrapRefArray(Array[Object]("1", "2", "3", "4", "5", "6", "7", Nil))*)
243+ """ .stripMargin
244+ }
245+
246+ @ Test def testListApplyAvoidsIntermediateArray_over3 = {
247+ checkApplyAvoidsIntermediateArray_examples(" over3" ):
248+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", "5", "6", List[Object]("7"))
249+ | def meth2: List[Object] = new ::("1", new ::("2", new ::("3", new ::("4", new ::("5", new ::("6", new ::(List(wrapRefArray(Array[Object]("7"))*), Nil)))))))
250+ """ .stripMargin
251+ }
252+
253+ @ Test def testListApplyAvoidsIntermediateArray_over4 = {
254+ checkApplyAvoidsIntermediateArray_examples(" over4" ):
255+ """ def meth1: List[Object] = List[Object]("1", "2", "3", "4", "5", List[Object]("6", "7"))
256+ | def meth2: List[Object] = new ::("1", new ::("2", new ::("3", new ::("4", new ::("5", new ::(List(wrapRefArray(Array[Object]("6", "7"))*), Nil))))))
257+ """ .stripMargin
258+ }
259+
260+ @ Test def testListApplyAvoidsIntermediateArray_max5 = {
261+ checkApplyAvoidsIntermediateArray_examples(" max5" ):
262+ """ def meth1: List[Object] = List[Object](List[Object](List[Object](List[Object](List[Object](List[Object](List[Object](List[Object]())))))))
263+ | def meth2: List[Object] = new ::(new ::(new ::(new ::(new ::(new ::(new ::(Nil, Nil), Nil), Nil), Nil), Nil), Nil), Nil)
264+ """ .stripMargin
265+ }
266+
267+ @ Test def testListApplyAvoidsIntermediateArray_over5 = {
268+ checkApplyAvoidsIntermediateArray_examples(" over5" ):
269+ """ def meth1: List[Object] = List[Object](List[Object](List[Object](List[Object](List[Object](List[Object](List[Object](List[Object](List[Object]()))))))))
270+ | def meth2: List[Object] = new ::(new ::(new ::(new ::(new ::(new ::(new ::(List[Object](wrapRefArray(Array[Object](Nil))*), Nil), Nil), Nil), Nil), Nil), Nil), Nil)
271+ """ .stripMargin
272+ }
273+
274+ @ Test def testListApplyAvoidsIntermediateArray_max6 = {
275+ checkApplyAvoidsIntermediateArray_examples(" max6" ):
276+ """ def meth1: List[Object] = List[Object]("1", "2", List[Object]("3", "4", List[Object](List[Object]())))
277+ | def meth2: List[Object] = new ::("1", new ::("2", new ::(new ::("3", new ::("4", new ::(new ::(Nil, Nil), Nil))), Nil)))
278+ """ .stripMargin
279+ }
280+
281+ @ Test def testListApplyAvoidsIntermediateArray_over6 = {
282+ checkApplyAvoidsIntermediateArray_examples(" over6" ):
283+ """ def meth1: List[Object] = List[Object]("1", "2", List[Object]("3", "4", List[Object]("5")))
284+ | def meth2: List[Object] = new ::("1", new ::("2", new ::(new ::("3", new ::("4", new ::(new ::("5", Nil), Nil))), Nil)))
285+ """ .stripMargin
286+ }
287+
288+ def checkApplyAvoidsIntermediateArray_examples (name : String )(body : String ): Unit = {
289+ checkApplyAvoidsIntermediateArray(s " List_ $name" ):
290+ s """ import scala.collection.immutable.{ ::, Nil }, scala.runtime.ScalaRunTime.wrapRefArray
291+ |class Foo {
292+ | $body
293+ |}
294+ """ .stripMargin
295+ }
296+
297+ def checkApplyAvoidsIntermediateArray (name : String )(source : String ): Unit = {
205298 checkBCode(source) { dir =>
206299 val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
207300 val clsNode = loadClassNode(clsIn)
208301 val meth1 = getMethod(clsNode, " meth1" )
209302 val meth2 = getMethod(clsNode, " meth2" )
210303
211- val instructions1 = instructionsFromMethod(meth1) match
212- case instr :+ TypeOp (CHECKCAST , _) :+ TypeOp (CHECKCAST , _) :+ (ret @ Op (ARETURN )) =>
213- instr :+ ret
214- case instr :+ TypeOp (CHECKCAST , _) :+ (ret @ Op (ARETURN )) =>
215- // List.apply[?A] doesn't, strictly, return List[?A],
216- // because it cascades to its definition on IterableFactory
217- // where it returns CC[A]. The erasure of that is Object,
218- // which is why Erasure's Typer adds a cast to compensate.
219- // If we drop that cast while optimising (because using
220- // the constructor for :: doesn't require the cast like
221- // List.apply did) then then cons construction chain will
222- // be typed as ::.
223- // Unfortunately the LUB of :: and Nil.type is Product
224- // instead of List, so a cast remains necessary,
225- // across whatever causes the lub, like `if` or `try` branches.
226- // Therefore if we dropping the cast may cause a needed cast
227- // to be necessary, we shouldn't drop the cast,
228- // which was only motivated by the assert here.
229- instr :+ ret
230- case instr => instr
231- val instructions2 = instructionsFromMethod(meth2)
304+ val instructions1 = instructionsFromMethod(meth1).filter { case TypeOp (CHECKCAST , _) => false case _ => true }
305+ val instructions2 = instructionsFromMethod(meth2).filter { case TypeOp (CHECKCAST , _) => false case _ => true }
232306
233307 assert(instructions1 == instructions2,
234308 s " the $name.apply method \n " +
0 commit comments