JVM_IR KT-45187 use Arrays.copyOf to copy an array in spread operator
Creating a new array (and copying data into it with System.arraycopy) doesn't work in generic case, because the actual array class depends on call site.
This commit is contained in:
committed by
TeamCityServer
parent
334d0a8b5a
commit
7d62f0b5aa
@@ -204,6 +204,15 @@ open class BuiltinSymbolsBase(protected val irBuiltIns: IrBuiltIns, protected va
|
||||
val doubleArray = primitiveArrayClass(PrimitiveType.DOUBLE)
|
||||
val booleanArray = primitiveArrayClass(PrimitiveType.BOOLEAN)
|
||||
|
||||
val byteArrayType get() = byteArray.owner.defaultType
|
||||
val charArrayType get() = charArray.owner.defaultType
|
||||
val shortArrayType get() = shortArray.owner.defaultType
|
||||
val intArrayType get() = intArray.owner.defaultType
|
||||
val longArrayType get() = longArray.owner.defaultType
|
||||
val floatArrayType get() = floatArray.owner.defaultType
|
||||
val doubleArrayType get() = doubleArray.owner.defaultType
|
||||
val booleanArrayType get() = booleanArray.owner.defaultType
|
||||
|
||||
val unsignedArrays = UnsignedType.values().mapNotNull { unsignedType ->
|
||||
unsignedArrayClass(unsignedType)?.let { unsignedType to it }
|
||||
}.toMap()
|
||||
|
||||
@@ -23,12 +23,12 @@ import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
|
||||
@@ -51,6 +51,7 @@ class JvmSymbols(
|
||||
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
||||
private val kotlinReflectPackage: IrPackageFragment = createPackage(FqName("kotlin.reflect"))
|
||||
private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang"))
|
||||
private val javaUtilPackage: IrPackageFragment = createPackage(FqName("java.util"))
|
||||
|
||||
// Special package for functions representing dynamic symbols referenced by 'INVOKEDYNAMIC' instruction - e.g.,
|
||||
// 'get(Ljava/lang/String;)Ljava/util/function/Supplier;'
|
||||
@@ -90,6 +91,7 @@ class JvmSymbols(
|
||||
"kotlin.jvm" -> kotlinJvmPackage
|
||||
"kotlin.reflect" -> kotlinReflectPackage
|
||||
"java.lang" -> javaLangPackage
|
||||
"java.util" -> javaUtilPackage
|
||||
else -> error("Other packages are not supported yet: $fqName")
|
||||
}
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
@@ -548,6 +550,7 @@ class JvmSymbols(
|
||||
}.symbol
|
||||
|
||||
val arrayOfAnyType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyType)
|
||||
val arrayOfAnyNType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType)
|
||||
|
||||
// Intrinsic to represent closure creation using INVOKEDYNAMIC with LambdaMetafactory.{metafactory, altMetafactory}
|
||||
// as a bootstrap method.
|
||||
@@ -742,13 +745,40 @@ class JvmSymbols(
|
||||
}
|
||||
}
|
||||
|
||||
private val systemClass: IrClassSymbol = createClass(FqName("java.lang.System")) { klass ->
|
||||
klass.addFunction("arraycopy", irBuiltIns.unitType, isStatic = true).apply {
|
||||
addValueParameter("src", irBuiltIns.anyNType)
|
||||
addValueParameter("srcPos", irBuiltIns.intType)
|
||||
addValueParameter("dest", irBuiltIns.anyNType)
|
||||
addValueParameter("destPos", irBuiltIns.intType)
|
||||
addValueParameter("length", irBuiltIns.intType)
|
||||
private val arraysCopyOfFunctions = HashMap<IrSimpleType, IrSimpleFunction>()
|
||||
|
||||
private fun IrClass.addArraysCopyOfFunction(arrayType: IrSimpleType) {
|
||||
addFunction("copyOf", arrayType, isStatic = true).apply {
|
||||
addValueParameter("original", arrayType)
|
||||
addValueParameter("newLength", irBuiltIns.intType)
|
||||
arraysCopyOfFunctions[arrayType] = this
|
||||
}
|
||||
}
|
||||
|
||||
val arraysClass: IrClassSymbol =
|
||||
createClass(FqName("java.util.Arrays")) { irClass ->
|
||||
irClass.addArraysCopyOfFunction(booleanArrayType)
|
||||
irClass.addArraysCopyOfFunction(byteArrayType)
|
||||
irClass.addArraysCopyOfFunction(charArrayType)
|
||||
irClass.addArraysCopyOfFunction(shortArrayType)
|
||||
irClass.addArraysCopyOfFunction(intArrayType)
|
||||
irClass.addArraysCopyOfFunction(longArrayType)
|
||||
irClass.addArraysCopyOfFunction(floatArrayType)
|
||||
irClass.addArraysCopyOfFunction(doubleArrayType)
|
||||
|
||||
// public static <T> T[] copyOf(T[] original, int newLength)
|
||||
irClass.addArraysCopyOfFunction(arrayOfAnyNType)
|
||||
}
|
||||
|
||||
fun getArraysCopyOfFunction(arrayType: IrSimpleType): IrSimpleFunctionSymbol {
|
||||
val copyOf = arraysCopyOfFunctions[arrayType]
|
||||
return when {
|
||||
copyOf != null ->
|
||||
copyOf.symbol
|
||||
arrayType.classifierOrFail == array ->
|
||||
arraysCopyOfFunctions[arrayOfAnyNType]!!.symbol
|
||||
else ->
|
||||
throw AssertionError("Array type expected: ${arrayType.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,8 +828,6 @@ class JvmSymbols(
|
||||
val remainderUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("remainderUnsigned")
|
||||
val toUnsignedStringLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("toUnsignedString")
|
||||
|
||||
val systemArraycopy: IrSimpleFunctionSymbol = systemClass.functionByName("arraycopy")
|
||||
|
||||
val signatureStringIntrinsic: IrSimpleFunctionSymbol =
|
||||
irFactory.buildFun {
|
||||
name = Name.special("<signature-string>")
|
||||
|
||||
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.getArrayElementType
|
||||
import org.jetbrains.kotlin.ir.types.isBoxedArray
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||
@@ -105,16 +102,12 @@ class IrArrayBuilder(val builder: JvmIrBuilder, val arrayType: IrType) {
|
||||
return builder.irBlock {
|
||||
val spreadVar = if (spread is IrGetValue) spread.symbol.owner else irTemporary(spread)
|
||||
val size = unwrappedArrayType.classOrNull!!.getPropertyGetter("size")!!
|
||||
fun getSize() = irCall(size).apply { dispatchReceiver = irGet(spreadVar) }
|
||||
val result = irTemporary(newArray(getSize()))
|
||||
+irCall(builder.irSymbols.systemArraycopy).apply {
|
||||
val arrayCopyOf = builder.irSymbols.getArraysCopyOfFunction(unwrappedArrayType as IrSimpleType)
|
||||
// TODO consider using System.arraycopy if the requested array type is non-generic.
|
||||
+irCall(arrayCopyOf).apply {
|
||||
putValueArgument(0, coerce(irGet(spreadVar), unwrappedArrayType))
|
||||
putValueArgument(1, irInt(0))
|
||||
putValueArgument(2, irGet(result))
|
||||
putValueArgument(3, irInt(0))
|
||||
putValueArgument(4, getSize())
|
||||
putValueArgument(1, irCall(size).apply { dispatchReceiver = irGet(spreadVar) })
|
||||
}
|
||||
+irGet(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user