@@ -201,34 +201,108 @@ class ArrayApplyOptTest extends DottyBytecodeTest {
201
201
""" .stripMargin
202
202
}
203
203
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 = {
205
298
checkBCode(source) { dir =>
206
299
val clsIn = dir.lookupName(" Foo.class" , directory = false ).input
207
300
val clsNode = loadClassNode(clsIn)
208
301
val meth1 = getMethod(clsNode, " meth1" )
209
302
val meth2 = getMethod(clsNode, " meth2" )
210
303
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 }
232
306
233
307
assert(instructions1 == instructions2,
234
308
s " the $name.apply method \n " +
0 commit comments