[JS IR] arrayConcat not use additional slice
This commit is contained in:
+37
-24
@@ -152,30 +152,11 @@ private class VarargTransformer(
|
||||
// vararg with a single segment => no need to concatenate
|
||||
if (segments.size == 1) {
|
||||
val segment = segments.first()
|
||||
if (expression in externalVarargs) {
|
||||
externalVarargs.remove(expression)
|
||||
return segment
|
||||
}
|
||||
val argument = if (expression.elements.any { it is IrSpreadElement }) {
|
||||
val elementType = arrayInfo.primitiveElementType
|
||||
val copyFunction =
|
||||
if (elementType.isChar() || elementType.isBoolean() || elementType.isLong())
|
||||
context.intrinsics.taggedArrayCopy
|
||||
else
|
||||
context.intrinsics.jsArraySlice
|
||||
|
||||
IrCallImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
arrayInfo.primitiveArrayType,
|
||||
copyFunction,
|
||||
typeArgumentsCount = 1,
|
||||
valueArgumentsCount = 1
|
||||
).apply {
|
||||
putTypeArgument(0, arrayInfo.primitiveArrayType)
|
||||
putValueArgument(0, segment)
|
||||
}
|
||||
} else segment
|
||||
val argument = getArgumentFromSingleSegment(
|
||||
expression,
|
||||
segment,
|
||||
arrayInfo
|
||||
)
|
||||
|
||||
return arrayInfo.boxArrayIfNeeded(argument)
|
||||
}
|
||||
@@ -206,6 +187,38 @@ private class VarargTransformer(
|
||||
return arrayInfo.boxArrayIfNeeded(res)
|
||||
}
|
||||
|
||||
private fun getArgumentFromSingleSegment(
|
||||
expression: IrVararg,
|
||||
segment: IrExpression,
|
||||
arrayInfo: InlineClassArrayInfo
|
||||
): IrExpression {
|
||||
if (expression in externalVarargs) {
|
||||
externalVarargs.remove(expression)
|
||||
return segment
|
||||
}
|
||||
|
||||
return if (expression.elements.any { it is IrSpreadElement }) {
|
||||
val elementType = arrayInfo.primitiveElementType
|
||||
val copyFunction =
|
||||
if (elementType.isChar() || elementType.isBoolean() || elementType.isLong())
|
||||
context.intrinsics.taggedArrayCopy
|
||||
else
|
||||
context.intrinsics.jsArraySlice
|
||||
|
||||
IrCallImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
arrayInfo.primitiveArrayType,
|
||||
copyFunction,
|
||||
typeArgumentsCount = 1,
|
||||
valueArgumentsCount = 1
|
||||
).apply {
|
||||
putTypeArgument(0, arrayInfo.primitiveArrayType)
|
||||
putValueArgument(0, segment)
|
||||
}
|
||||
} else segment
|
||||
}
|
||||
|
||||
private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression {
|
||||
if (expression.symbol.owner.isExternal) {
|
||||
for (i in 0 until expression.valueArgumentsCount) {
|
||||
|
||||
+2
@@ -170,6 +170,8 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
JsNew(refForExternalClass, arguments)
|
||||
} else {
|
||||
val argumentsAsSingleArray = argumentsWithVarargAsSingleArray(
|
||||
expression,
|
||||
context,
|
||||
JsNullLiteral(),
|
||||
arguments,
|
||||
varargParameterIndex
|
||||
|
||||
+10
-1
@@ -156,6 +156,8 @@ fun translateCall(
|
||||
// TODO: Don't use `Function.prototype.apply` when number of arguments is known at compile time (e.g. there are no spread operators)
|
||||
|
||||
val argumentsAsSingleArray = argumentsWithVarargAsSingleArray(
|
||||
expression,
|
||||
context,
|
||||
jsExtensionReceiver,
|
||||
arguments,
|
||||
varargParameterIndex
|
||||
@@ -223,6 +225,8 @@ fun translateCall(
|
||||
}
|
||||
|
||||
fun argumentsWithVarargAsSingleArray(
|
||||
expression: IrFunctionAccessExpression,
|
||||
context: JsGenerationContext,
|
||||
additionalReceiver: JsExpression?,
|
||||
arguments: List<JsExpression>,
|
||||
varargParameterIndex: Int,
|
||||
@@ -241,6 +245,8 @@ fun argumentsWithVarargAsSingleArray(
|
||||
|
||||
// Call `Array.prototype.slice` on vararg arguments in order to convert array-like objects into proper arrays
|
||||
varargParameterIndex -> {
|
||||
val valueArgument = expression.getValueArgument(varargParameterIndex)
|
||||
|
||||
if (arraysForConcat.isNotEmpty()) {
|
||||
concatElements.add(JsArrayLiteral(arraysForConcat))
|
||||
}
|
||||
@@ -250,7 +256,10 @@ fun argumentsWithVarargAsSingleArray(
|
||||
is JsArrayLiteral -> argument
|
||||
is JsNew -> argument.arguments.firstOrNull() as? JsArrayLiteral
|
||||
else -> null
|
||||
} ?: JsInvocation(JsNameRef("call", JsNameRef("slice", JsArrayLiteral())), argument)
|
||||
} ?: if (valueArgument is IrCall && valueArgument.symbol == context.staticContext.backendContext.intrinsics.arrayConcat)
|
||||
argument
|
||||
else
|
||||
JsInvocation(JsNameRef("call", JsNameRef("slice", JsArrayLiteral())), argument)
|
||||
|
||||
concatElements.add(varargArgument)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user