-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
dotty.runtime.Arrays has a bunch of magic methods, including the very magic newRefArray, which is one of the 3 methods that stay generic after erasure.
It is very easy to get rid of this complexity, by given an actual parameter of type Class[T] to newRefArray:
def newRefArray[T <: AnyRef](componentType: Class[T], length: Int): Array[T]The back-end still needs to know about this magic method, and "assume" that componentType is a Literal(Constant(tpe)) (i.e., crash if it isn't). But then the method does not need to be generic anymore after erasure, which is a substantial win, IMO.
We can remove even more magic by given actual bodies to all the newXArray method, leveraging java.lang.reflect.Array.newInstance:
def newRefArray[T <: AnyRef](componentType: Class[T], length: Int): Array[T] =
java.lang.reflect.Array.newInstance(componentType, length).asInstanceOf[Array[T]]
def newByteArray(length: Int): Array[Byte] =
java.lang.reflect.Array.newInstance(classOf[Byte], length).asInstanceOf[Array[Byte]]
...
def newUnitArray(length: Int): Array[Unit] =
java.lang.reflect.Array.newInstance(classOf[BoxedUnit], length).asInstanceOf[Array[Unit]]and now the back-end does not need to treat these methods specially. Their user-space implementation is perfectly correct.
Of course, on the JVM, that implementation is inefficient, so the JVM back-end would still specialize them. But other back-ends need not have the same problem. For example, Scala.js does not need to specialize those to get full speed, because Array.newInstance is intrisified by the optimizer when the componentType is a literal classOf.