[JS IR] Not use double slice for external varargs

This commit is contained in:
Ilya Goncharov
2021-03-04 16:04:32 +03:00
parent 120b5b9e05
commit b8d5712bc0
@@ -16,7 +16,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.getInlineClassBackingField
import org.jetbrains.kotlin.ir.util.getInlineClassUnderlyingType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -26,12 +29,15 @@ class VarargLowering(val context: JsIrBackendContext) : BodyLoweringPass {
irBody.transformChildrenVoid(VarargTransformer(context)) irBody.transformChildrenVoid(VarargTransformer(context))
} }
} }
private class VarargTransformer( private class VarargTransformer(
val context: JsIrBackendContext val context: JsIrBackendContext
) : IrElementTransformerVoid() { ) : IrElementTransformerVoid() {
fun IrType.getInlinedClass() = context.inlineClassesUtils.getInlinedClass(this) fun IrType.getInlinedClass() = context.inlineClassesUtils.getInlinedClass(this)
var externalVarargs = mutableSetOf<IrVararg>()
private fun List<IrExpression>.toArrayLiteral(type: IrType, varargElementType: IrType): IrExpression { private fun List<IrExpression>.toArrayLiteral(type: IrType, varargElementType: IrType): IrExpression {
// TODO: Use symbols when builtins symbol table is fixes // TODO: Use symbols when builtins symbol table is fixes
@@ -138,7 +144,7 @@ private class VarargTransformer(
// empty vararg => empty array literal // empty vararg => empty array literal
if (segments.isEmpty()) { if (segments.isEmpty()) {
with (arrayInfo) { with(arrayInfo) {
return boxArrayIfNeeded(toPrimitiveArrayLiteral(emptyList<IrExpression>())) return boxArrayIfNeeded(toPrimitiveArrayLiteral(emptyList<IrExpression>()))
} }
} }
@@ -146,6 +152,10 @@ private class VarargTransformer(
// vararg with a single segment => no need to concatenate // vararg with a single segment => no need to concatenate
if (segments.size == 1) { if (segments.size == 1) {
val segment = segments.first() val segment = segments.first()
if (expression in externalVarargs) {
externalVarargs.remove(expression)
return segment
}
val argument = if (expression.elements.any { it is IrSpreadElement }) { val argument = if (expression.elements.any { it is IrSpreadElement }) {
val elementType = arrayInfo.primitiveElementType val elementType = arrayInfo.primitiveElementType
val copyFunction = val copyFunction =
@@ -197,6 +207,17 @@ private class VarargTransformer(
} }
private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression { private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression {
if (expression.symbol.owner.isExternal) {
for (i in 0 until expression.valueArgumentsCount) {
val parameter = expression.symbol.owner.valueParameters[i]
val varargElementType = parameter.varargElementType
if (varargElementType != null) {
(expression.getValueArgument(i) as IrVararg?)?.let {
externalVarargs.add(it)
}
}
}
}
expression.transformChildrenVoid() expression.transformChildrenVoid()
val size = expression.valueArgumentsCount val size = expression.valueArgumentsCount
@@ -206,7 +227,7 @@ private class VarargTransformer(
val varargElementType = parameter.varargElementType val varargElementType = parameter.varargElementType
if (argument == null && varargElementType != null) { if (argument == null && varargElementType != null) {
val arrayInfo = InlineClassArrayInfo(varargElementType, parameter.type) val arrayInfo = InlineClassArrayInfo(varargElementType, parameter.type)
val emptyArray = with (arrayInfo) { val emptyArray = with(arrayInfo) {
boxArrayIfNeeded(toPrimitiveArrayLiteral(emptyList())) boxArrayIfNeeded(toPrimitiveArrayLiteral(emptyList()))
} }