From 039b5fca7a9e7b5200aac98ff693ada34903836f Mon Sep 17 00:00:00 2001 From: Artem Kobzar Date: Tue, 20 Jun 2023 12:01:28 +0000 Subject: [PATCH] [K/JS] Use declared upper-bound types for parameters inside inlined functions body, instead of the provided types --- .../common/lower/inline/FunctionInlining.kt | 30 +++++-- .../kotlin/ir/backend/js/JsLoweringPhases.kt | 12 ++- .../ir/backend/js/lower/ConstLowering.kt | 6 -- .../irToJs/JsIntrinsicTransformers.kt | 5 +- .../inlineWithoutStateMachine.kt | 2 +- ...thInlineFunctionWithMultipleConstraints.kt | 32 ++++++++ ...boxParameterOfSuspendLambdaBeforeInvoke.kt | 2 - ...meterOfSuspendLambdaBeforeInvokeGeneric.kt | 2 - .../testData/debug/localVariables/jsCode.kt | 1 + compiler/testData/debug/stepping/assertion.kt | 1 + .../debug/stepping/functionCallWithDefault.kt | 2 +- .../stepping/inlineNamedCallableReference.kt | 2 +- .../ast/metadata/metadataProperties.kt | 3 + .../inline/clean/BoxingUnboxingElimination.kt | 80 +++++++++++++++++++ .../js/inline/clean/FunctionPostProcessor.kt | 3 +- .../kotlin/js/test/BoxJsTestGenerated.java | 6 ++ .../js/test/fir/FirJsBoxTestGenerated.java | 6 ++ .../fir/FirJsCodegenBoxTestGenerated.java | 6 ++ .../js/test/ir/IrBoxJsES6TestGenerated.java | 6 ++ .../js/test/ir/IrBoxJsTestGenerated.java | 6 ++ .../test/ir/IrJsCodegenBoxTestGenerated.java | 6 ++ .../ir/IrJsES6CodegenBoxTestGenerated.java | 6 ++ .../testData/box/coercion/defaultAccessors.kt | 1 + .../box/coercion/extensionReceiver.kt | 2 + .../box/coercion/propertyBridgeChar.kt | 1 + .../box/coercion/receiverSmartCast.kt | 2 + .../box/dynamic/lambdaParameterInlining.kt | 17 ++++ .../testData/box/inline/inlineClassEquals.kt | 3 +- .../testData/box/reified/isTNullable.kt | 3 +- .../box/standardClasses/charArrayGetSet.kt | 1 + .../testData/lineNumbers/coroutine.kt | 3 +- .../lineNumbers/destructuringInline.kt | 2 +- js/js.translator/testData/lineNumbers/for.kt | 5 +- .../lineNumbers/inlineLocalVarsRef.kt | 2 +- .../lineNumbers/inlineMultiModule/simple.kt | 4 +- .../stdlib/js-ir/src/generated/_ArraysJs.kt | 19 ++--- .../stdlib/js/src/generated/_ArraysJs.kt | 19 ++--- .../kotlin-stdlib-gen/src/templates/Arrays.kt | 13 ++- 38 files changed, 269 insertions(+), 53 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt create mode 100644 js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/BoxingUnboxingElimination.kt create mode 100644 js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt index 62c45dafbc4..c253af4f438 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.backend.common.lower.inline -import org.jetbrains.kotlin.backend.common.BodyLoweringPass -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.ScopeWithIr +import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.isPure import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport @@ -90,7 +87,8 @@ class FunctionInlining( private val inlinePureArguments: Boolean = true, private val regenerateInlinedAnonymousObjects: Boolean = false, private val inlineArgumentsWithTheirOriginalTypeAndOffset: Boolean = false, - private val allowExternalInlining: Boolean = false + private val allowExternalInlining: Boolean = false, + private val useTypeParameterUpperBound: Boolean = false ) : IrElementTransformerVoidWithContext(), BodyLoweringPass { private var containerScope: ScopeWithIr? = null @@ -746,7 +744,8 @@ class FunctionInlining( // We take type parameter from copied callee and not from original because we need an actual copy. Without this copy, // in case of recursive call, we can get a situation there the same type parameter will be mapped on different type arguments. // (see compiler/testData/codegen/boxInline/complex/use.kt test file) - return copy.typeParameters[typeClassifier.index].defaultType.substituteSuperTypes() + val newTypeParameter = copy.typeParameters[typeClassifier.index].defaultType.substituteSuperTypes() + return if (useTypeParameterUpperBound) typeClassifier.firstRealUpperBound() else newTypeParameter } return when (this) { @@ -755,12 +754,29 @@ class FunctionInlining( copy.extensionReceiverParameter -> original.extensionReceiverParameter?.getTypeIfFromTypeParameter() ?: copy.extensionReceiverParameter!!.type else -> copy.valueParameters.first { it == this }.let { valueParameter -> - original.valueParameters[valueParameter.index].getTypeIfFromTypeParameter() + original.valueParameters.getOrNull(valueParameter.index)?.getTypeIfFromTypeParameter() ?: valueParameter.type } } } + private fun IrTypeParameter?.firstRealUpperBound(): IrType { + val queue = this?.superTypes?.toMutableList() ?: mutableListOf() + + while (queue.isNotEmpty()) { + val superType = queue.removeFirst() + val superTypeClassifier = superType.classifierOrNull?.owner ?: continue + + if (superTypeClassifier is IrTypeParameter) { + queue.addAll(superTypeClassifier.superTypes) + } else { + return superType + } + } + + return context.irBuiltIns.anyNType + } + private fun evaluateArguments(callSite: IrFunctionAccessExpression, callee: IrFunction): List { val arguments = buildParameterToArgument(callSite, callee) val evaluationStatements = mutableListOf() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 9d1aad360bd..6e52dd5f6d7 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -280,7 +280,17 @@ private val saveInlineFunctionsBeforeInlining = makeDeclarationTransformerPhase( ) private val functionInliningPhase = makeBodyLoweringPhase( - { FunctionInlining(it, JsInlineFunctionResolver(it), it.innerClassesSupport, allowExternalInlining = true) }, + { + FunctionInlining( + it, + JsInlineFunctionResolver(it), + it.innerClassesSupport, + allowExternalInlining = true, + useTypeParameterUpperBound = true, + alwaysCreateTemporaryVariablesForArguments = true, + inlineArgumentsWithTheirOriginalTypeAndOffset = true + ) + }, name = "FunctionInliningPhase", description = "Perform function inlining", prerequisite = setOf(saveInlineFunctionsBeforeInlining) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt index 5153b2cf63e..31620c3f3ea 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt @@ -8,20 +8,14 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.compilationException import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext -import org.jetbrains.kotlin.ir.backend.js.utils.getVoid -import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.defaultType diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index 3beb8e2d89e..324422baa92 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -23,6 +23,8 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.getInlineClassBackingField import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineClassBoxing +import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineClassUnboxing typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression @@ -179,6 +181,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { val inlineClass = icUtils.getInlinedClass(call.getTypeArgument(0)!!)!! val constructor = inlineClass.declarations.filterIsInstance().single { it.isPrimary } JsNew(context.getNameForConstructor(constructor).makeRef(), listOf(arg)) + .apply { isInlineClassBoxing = true } } add(intrinsics.jsUnboxIntrinsic) { call, context -> @@ -186,7 +189,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { val inlineClass = icUtils.getInlinedClass(call.getTypeArgument(1)!!)!! val field = getInlineClassBackingField(inlineClass) val fieldName = context.getNameForField(field) - JsNameRef(fieldName, arg) + JsNameRef(fieldName, arg).apply { isInlineClassUnboxing = true } } add(intrinsics.jsCall) { call, context: JsGenerationContext -> diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.kt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.kt index c35fea7624f..530d12cfff5 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.kt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.kt @@ -2,7 +2,7 @@ // WITH_COROUTINES // CHECK_BYTECODE_LISTING // FIR_IDENTICAL -// CHECK_NEW_COUNT: function=suspendHere count=0 +// CHECK_NEW_COUNT: function=suspendHere count=0 TARGET_BACKENDS=JS // FIXME: Coroutine inlining // CHECK_NEW_COUNT: function=complexSuspend count=0 TARGET_BACKENDS=JS import helpers.* diff --git a/compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt b/compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt new file mode 100644 index 00000000000..8b75c60cef9 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt @@ -0,0 +1,32 @@ +// WITH_STDLIB +// WORKS_WHEN_VALUE_CLASS +// LANGUAGE: +ValueClasses +// TARGET_BACKEND: JS_IR +// TARGET_BACKEND: JS_IR_ES6 + +interface Foo { + fun foo(): String + fun bar(): String +} + +value class Value(val x: Int) : Foo, Comparable { + override fun foo() = "FOO $x" + + override fun bar() = "BAR $x" + + override fun compareTo(other: Value) = x.compareTo(other.x) +} + +inline fun foo(a: T, b: T): String where T: Foo, T: Comparable { + return if (a > b) a.foo() else b.foo() +} + +inline fun bar(a: T, b: T): String where T: Comparable, T: Foo { + return if (a > b) a.bar() else b.bar() +} + +fun box(): String { + if (foo(Value(1), Value(2)) != "FOO 2") return "Fail" + if (bar(Value(2), Value(1)) != "BAR 2") return "Fail" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvoke.kt b/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvoke.kt index 9ab803bc214..a57e2496faf 100644 --- a/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvoke.kt +++ b/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvoke.kt @@ -2,8 +2,6 @@ // WASM_MUTE_REASON: IGNORED_IN_JS // WITH_COROUTINES // WITH_STDLIB -// IGNORE_BACKEND: JS_IR -// IGNORE_BACKEND: JS_IR_ES6 // WORKS_WHEN_VALUE_CLASS // LANGUAGE: +ValueClasses diff --git a/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvokeGeneric.kt b/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvokeGeneric.kt index 4304a3ae029..999b94850ec 100644 --- a/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvokeGeneric.kt +++ b/compiler/testData/codegen/box/inlineClasses/unboxParameterOfSuspendLambdaBeforeInvokeGeneric.kt @@ -2,8 +2,6 @@ // WASM_MUTE_REASON: IGNORED_IN_JS // WITH_COROUTINES // WITH_STDLIB -// IGNORE_BACKEND: JS_IR -// IGNORE_BACKEND: JS_IR_ES6 // WORKS_WHEN_VALUE_CLASS // LANGUAGE: +ValueClasses, +GenericInlineClassParameter diff --git a/compiler/testData/debug/localVariables/jsCode.kt b/compiler/testData/debug/localVariables/jsCode.kt index 5e63521cef0..934ae22facf 100644 --- a/compiler/testData/debug/localVariables/jsCode.kt +++ b/compiler/testData/debug/localVariables/jsCode.kt @@ -81,6 +81,7 @@ fun box() { // a.kt:6 exclamate: s="Jesse":kotlin.String // test.kt:52 box: jesse="Jesse":kotlin.String, walter1="Walter!":kotlin.String, jesse1="Jesse!":kotlin.String // a.kt:6 exclamate: s="Jesse!":kotlin.String +// a.kt:19 box: jesse="Jesse":kotlin.String, walter1="Walter!":kotlin.String, jesse1="Jesse!":kotlin.String // a.kt:22 value: // test.kt:63 box: jesse="Jesse":kotlin.String, walter1="Walter!":kotlin.String, jesse1="Jesse!":kotlin.String // test.kt:59 localFun: hello="hello":kotlin.String, world="world":kotlin.String diff --git a/compiler/testData/debug/stepping/assertion.kt b/compiler/testData/debug/stepping/assertion.kt index 21768d4fb32..c4d1072fede 100644 --- a/compiler/testData/debug/stepping/assertion.kt +++ b/compiler/testData/debug/stepping/assertion.kt @@ -47,6 +47,7 @@ fun box(): String { // test.kt:30 box // EXPECTATIONS JS_IR +// test.kt:16 box // test.kt:17 box // test.kt:7 box // test.kt:30 box diff --git a/compiler/testData/debug/stepping/functionCallWithDefault.kt b/compiler/testData/debug/stepping/functionCallWithDefault.kt index 7bbc8e78247..1067d0a2384 100644 --- a/compiler/testData/debug/stepping/functionCallWithDefault.kt +++ b/compiler/testData/debug/stepping/functionCallWithDefault.kt @@ -25,4 +25,4 @@ inline fun bar(i: Int = 1) { // EXPECTATIONS JS_IR // test.kt:4 box // test.kt:9 foo -// test.kt:6 box \ No newline at end of file +// test.kt:6 box diff --git a/compiler/testData/debug/stepping/inlineNamedCallableReference.kt b/compiler/testData/debug/stepping/inlineNamedCallableReference.kt index 36d15fa2f5e..e10a7d0b4f8 100644 --- a/compiler/testData/debug/stepping/inlineNamedCallableReference.kt +++ b/compiler/testData/debug/stepping/inlineNamedCallableReference.kt @@ -22,6 +22,6 @@ fun g() {} // EXPECTATIONS JS_IR // test.kt:3 box -// test.kt:8 box +// test.kt:4 box // test.kt:11 g // test.kt:5 box \ No newline at end of file diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt index 0aec0c1693c..94573ab6616 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt @@ -79,6 +79,9 @@ var JsReturn.returnTarget: FunctionDescriptor? by MetadataProperty(default = nul var HasMetadata.synthetic: Boolean by MetadataProperty(default = false) +var HasMetadata.isInlineClassBoxing: Boolean by MetadataProperty(default = false) +var HasMetadata.isInlineClassUnboxing: Boolean by MetadataProperty(default = false) + var HasMetadata.sideEffects: SideEffectKind by MetadataProperty(default = SideEffectKind.AFFECTS_STATE) /** diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/BoxingUnboxingElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/BoxingUnboxingElimination.kt new file mode 100644 index 00000000000..d8b6f6cf9d6 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/BoxingUnboxingElimination.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.inline.clean + +import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.JsExpression.JsExpressionHasArguments +import org.jetbrains.kotlin.js.backend.ast.metadata.HasMetadata +import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineClassBoxing +import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineClassUnboxing +import org.jetbrains.kotlin.js.backend.ast.metadata.isJsCall +import org.jetbrains.kotlin.js.inline.util.isCallInvocation + +// Replaces box(unbox(value)) and unbox(box(value)) with value +class BoxingUnboxingElimination(private val root: JsBlock) { + private var changed = false + + fun apply(): Boolean { + val visitor = object : JsVisitorWithContextImpl() { + override fun endVisit(x: JsInvocation, ctx: JsContext) { + super.endVisit(x, ctx) + tryEliminate(x, ctx) + } + + override fun endVisit(x: JsNew, ctx: JsContext) { + super.endVisit(x, ctx) + tryEliminate(x, ctx) + } + + + override fun endVisit(x: JsNameRef, ctx: JsContext) { + super.endVisit(x, ctx) + tryEliminate(x, ctx) + } + + override fun endVisit(x: JsArrayAccess, ctx: JsContext<*>) { + super.endVisit(x, ctx) + } + + override fun visit(x: JsFunction, ctx: JsContext) = false + + private fun tryEliminate(expression: JsExpression, ctx: JsContext) { + if (!expression.isInlineClassBoxing && !expression.isInlineClassUnboxing) return + + val firstArg = expression.arguments.first() + + if (!firstArg.isInlineClassBoxing && !firstArg.isInlineClassUnboxing) return + + if (firstArg.isInlineClassBoxing != expression.isInlineClassBoxing) { + ctx.replaceMe(firstArg.arguments.first()) + changed = true + } + } + + private val JsExpression.arguments: List + get() = when (this) { + is JsExpressionHasArguments -> arguments + is JsNameRef -> listOfNotNull(qualifier) + else -> emptyList() + } + } + + visitor.accept(root) + + return changed + } +} diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt index 28e5d05e95e..7a61018ba7b 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt @@ -31,7 +31,8 @@ class FunctionPostProcessor(val root: JsFunction) { { DeadCodeElimination(root.body).apply() }, { RedundantVariableDeclarationElimination(root.body).apply() }, { RedundantStatementElimination(root).apply() }, - { CoroutineStateElimination(root.body).apply() } + { CoroutineStateElimination(root.body).apply() }, + { BoxingUnboxingElimination(root.body).apply() } ) // TODO: reduce to A || B, A && B if possible diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java index dcb3ad47a35..0eae0358821 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java @@ -1692,6 +1692,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/dynamic/iterator.kt"); } + @Test + @TestMetadata("lambdaParameterInlining.kt") + public void testLambdaParameterInlining() throws Exception { + runTest("js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt"); + } + @Test @TestMetadata("nameClashing.kt") public void testNameClashing() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java index 8306cc5d03c..ed6eabf5e62 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java @@ -1762,6 +1762,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest { runTest("js/js.translator/testData/box/dynamic/iterator.kt"); } + @Test + @TestMetadata("lambdaParameterInlining.kt") + public void testLambdaParameterInlining() throws Exception { + runTest("js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt"); + } + @Test @TestMetadata("operationsWithAssignment.kt") public void testOperationsWithAssignment() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java index 6aa9b2e3f7c..44d68eddd56 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java @@ -18570,6 +18570,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986Generic.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); } + @Test + @TestMetadata("withInlineFunctionWithMultipleConstraints.kt") + public void testWithInlineFunctionWithMultipleConstraints() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); + } + @Nested @TestMetadata("compiler/testData/codegen/box/inlineClasses/callableReferences/let") @TestDataPath("$PROJECT_ROOT") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java index d6f9bec823e..77532aee601 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java @@ -1762,6 +1762,12 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/dynamic/iterator.kt"); } + @Test + @TestMetadata("lambdaParameterInlining.kt") + public void testLambdaParameterInlining() throws Exception { + runTest("js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt"); + } + @Test @TestMetadata("operationsWithAssignment.kt") public void testOperationsWithAssignment() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index 4def27bfc9e..650b5a1eea8 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -1762,6 +1762,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/dynamic/iterator.kt"); } + @Test + @TestMetadata("lambdaParameterInlining.kt") + public void testLambdaParameterInlining() throws Exception { + runTest("js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt"); + } + @Test @TestMetadata("operationsWithAssignment.kt") public void testOperationsWithAssignment() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index d78068a50bb..3f98d18d047 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -18570,6 +18570,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986Generic.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); } + @Test + @TestMetadata("withInlineFunctionWithMultipleConstraints.kt") + public void testWithInlineFunctionWithMultipleConstraints() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); + } + @Nested @TestMetadata("compiler/testData/codegen/box/inlineClasses/callableReferences/let") @TestDataPath("$PROJECT_ROOT") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java index 522b9be1a13..e00e3f388ed 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java @@ -18570,6 +18570,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986Generic.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); } + @Test + @TestMetadata("withInlineFunctionWithMultipleConstraints.kt") + public void testWithInlineFunctionWithMultipleConstraints() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/withInlineFunctionWithMultipleConstraints.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); + } + @Nested @TestMetadata("compiler/testData/codegen/box/inlineClasses/callableReferences/let") @TestDataPath("$PROJECT_ROOT") diff --git a/js/js.translator/testData/box/coercion/defaultAccessors.kt b/js/js.translator/testData/box/coercion/defaultAccessors.kt index 92dbe4f166e..e14b7a51c3f 100644 --- a/js/js.translator/testData/box/coercion/defaultAccessors.kt +++ b/js/js.translator/testData/box/coercion/defaultAccessors.kt @@ -1,4 +1,5 @@ // EXPECTED_REACHABLE_NODES: 1288 +// IGNORE_BACKEND: JS_IR, JS_IR_ES6 @JsExport interface I { diff --git a/js/js.translator/testData/box/coercion/extensionReceiver.kt b/js/js.translator/testData/box/coercion/extensionReceiver.kt index 1b247053d73..e5bf3f76ba7 100644 --- a/js/js.translator/testData/box/coercion/extensionReceiver.kt +++ b/js/js.translator/testData/box/coercion/extensionReceiver.kt @@ -1,4 +1,6 @@ // EXPECTED_REACHABLE_NODES: 1282 +// IGNORE_BACKEND: JS_IR, JS_IR_ES6 + fun box(): String { val a = 'Q'.foo() if (a != "number") return "fail1: $a" diff --git a/js/js.translator/testData/box/coercion/propertyBridgeChar.kt b/js/js.translator/testData/box/coercion/propertyBridgeChar.kt index 5fa6f4df973..4ba65e892e3 100644 --- a/js/js.translator/testData/box/coercion/propertyBridgeChar.kt +++ b/js/js.translator/testData/box/coercion/propertyBridgeChar.kt @@ -1,4 +1,5 @@ // EXPECTED_REACHABLE_NODES: 1289 +// IGNORE_BACKEND: JS_IR, JS_IR_ES6 @JsExport open class A { diff --git a/js/js.translator/testData/box/coercion/receiverSmartCast.kt b/js/js.translator/testData/box/coercion/receiverSmartCast.kt index 0ba720655bc..a6734c38079 100644 --- a/js/js.translator/testData/box/coercion/receiverSmartCast.kt +++ b/js/js.translator/testData/box/coercion/receiverSmartCast.kt @@ -1,4 +1,6 @@ // EXPECTED_REACHABLE_NODES: 1283 +// IGNORE_BACKEND: JS_IR, JS_IR_ES6 + fun foo(x: Any): String { return when (x) { is Char -> "char: ${x.toInt()}" diff --git a/js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt b/js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt new file mode 100644 index 00000000000..54e9bed7034 --- /dev/null +++ b/js/js.translator/testData/box/dynamic/lambdaParameterInlining.kt @@ -0,0 +1,17 @@ +// WITH_STDLIB + +fun demo(x: dynamic, a: Array): Boolean? { + return a.any { y: Any -> + val newX: Any = x.unsafeCast() + y == newX + } +} + +data class X(val x: Int) + +fun box(): String { + + if (demo(X(1), arrayOf(X(1))) != true) return "fail" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/inline/inlineClassEquals.kt b/js/js.translator/testData/box/inline/inlineClassEquals.kt index 87703d6a615..312fee341ef 100644 --- a/js/js.translator/testData/box/inline/inlineClassEquals.kt +++ b/js/js.translator/testData/box/inline/inlineClassEquals.kt @@ -317,8 +317,7 @@ fun testCompareDifferentInstancesInSmartCast() { fun testCompareDifferentInstncesInInlineTemplate() { inline fun myEq(x: T, y: S) = x == y - // CHECK_NOT_CALLED_IN_SCOPE: scope=testCompareDifferentInstncesInInlineTemplate$caseJsEq function=equals - // CHECK_NEW_COUNT: function=testCompareDifferentInstncesInInlineTemplate$caseJsEq count=0 + // CHECK_NEW_COUNT: function=testCompareDifferentInstncesInInlineTemplate$caseJsEq count=8 fun caseJsEq() { assertTrue(myEq(ClassInt(1), ClassInt(1))) assertTrue(myEq(ClassString("foo"), ClassString("foo"))) diff --git a/js/js.translator/testData/box/reified/isTNullable.kt b/js/js.translator/testData/box/reified/isTNullable.kt index b3532f33f6d..01183a62e1a 100644 --- a/js/js.translator/testData/box/reified/isTNullable.kt +++ b/js/js.translator/testData/box/reified/isTNullable.kt @@ -2,8 +2,7 @@ package foo // CHECK_NOT_CALLED: isTypeOfOrNull -// CHECK_NULLS_COUNT: function=box count=10 TARGET_BACKENDS=JS -// CHECK_NULLS_COUNT: function=box count=6 IGNORED_BACKENDS=JS +// CHECK_NULLS_COUNT: function=box count=10 inline fun Any?.isTypeOfOrNull() = this is T? diff --git a/js/js.translator/testData/box/standardClasses/charArrayGetSet.kt b/js/js.translator/testData/box/standardClasses/charArrayGetSet.kt index 12781d34014..6b37ab508bb 100644 --- a/js/js.translator/testData/box/standardClasses/charArrayGetSet.kt +++ b/js/js.translator/testData/box/standardClasses/charArrayGetSet.kt @@ -1,4 +1,5 @@ // EXPECTED_REACHABLE_NODES: 1281 +// IGNORE_BACKEND: JS_IR, JS_IR_ES6 fun box(): String { val a = CharArray(1) diff --git a/js/js.translator/testData/lineNumbers/coroutine.kt b/js/js.translator/testData/lineNumbers/coroutine.kt index 5d0a8d35879..1b3f91b71fa 100644 --- a/js/js.translator/testData/lineNumbers/coroutine.kt +++ b/js/js.translator/testData/lineNumbers/coroutine.kt @@ -15,4 +15,5 @@ suspend fun bar(): Unit { } // LINES(JS): 39 4 4 4 7 5 5 45 45 5 93 45 5 5 6 4 4 4 9 15 9 9 9 * 9 15 10 10 11 11 11 11 11 * 11 12 12 13 13 13 13 13 13 13 14 14 * 9 15 9 9 9 9 -// LINES(JS_IR): 4 4 * 93 93 45 45 7 7 6 9 9 * 9 * 9 * 10 10 * 11 * 11 12 12 * 13 * 13 14 14 15 15 +// LINES(JS_IR): 4 4 * 93 93 3 45 45 7 7 6 9 9 * 9 * 9 * 10 10 * 11 * 11 12 12 * 13 * 13 14 14 15 15 + diff --git a/js/js.translator/testData/lineNumbers/destructuringInline.kt b/js/js.translator/testData/lineNumbers/destructuringInline.kt index 6a6508adae9..7160162179f 100644 --- a/js/js.translator/testData/lineNumbers/destructuringInline.kt +++ b/js/js.translator/testData/lineNumbers/destructuringInline.kt @@ -33,4 +33,4 @@ inline operator fun P.component1() = a inline operator fun P.component2() = b // LINES(JS): 15 22 17 17 31 18 18 33 20 20 21 21 22 22 3 23 9 9 9 9 4 9 9 9 6 6 31 7 7 33 11 11 12 12 15 15 25 27 26 26 29 29 29 * 31 31 31 33 33 33 * 1 * 1 -// LINES(JS_IR): 1 1 1 1 1 1 1 1 * 3 3 9 9 4 9 * 6 31 * 7 33 11 11 12 12 15 15 25 25 26 26 29 29 29 29 29 29 29 29 29 29 29 29 31 31 31 31 33 33 33 33 15 16 15 * 17 31 * 18 33 20 20 21 21 22 22 * 1 +// LINES(JS_IR): 1 1 1 1 1 1 1 1 * 3 3 9 9 4 9 * 6 31 9 * 7 33 9 11 11 12 12 15 15 25 25 26 26 29 29 29 29 29 29 29 29 29 29 29 29 31 31 31 31 33 33 33 33 15 16 15 * 17 31 16 * 18 33 16 20 20 21 21 22 22 * 1 diff --git a/js/js.translator/testData/lineNumbers/for.kt b/js/js.translator/testData/lineNumbers/for.kt index 282e153fce5..6027502de84 100644 --- a/js/js.translator/testData/lineNumbers/for.kt +++ b/js/js.translator/testData/lineNumbers/for.kt @@ -17,5 +17,6 @@ fun box() { } } -// LINES(JS): 1 18 2 2 10 2 2 2 2 2 2 3 3 6 6 6 6 7 7 10 10 10 10 10 10 11 11 14 14 15 15 15 15 16 16 -// LINES(JS_IR): 1 1 * 2 2 2 2 2 2 2 2 3 3 6 6 6 6 6 6 6 7 7 10 10 10 10 11 11 14 15 15 15 15 15 15 15 15 16 16 +// LINES(JS): 1 18 2 2 10 2 2 2 2 2 2 3 3 6 6 6 6 7 7 10 10 10 10 10 10 11 11 14 14 15 15 15 15 16 16 +// LINES(JS_IR): 1 1 * 2 2 2 2 2 2 2 2 3 3 6 6 6 6 6 6 6 7 7 10 10 10 10 11 11 14 15 15 15 15 15 15 15 15 16 16 + diff --git a/js/js.translator/testData/lineNumbers/inlineLocalVarsRef.kt b/js/js.translator/testData/lineNumbers/inlineLocalVarsRef.kt index 2e76b42bb57..79c6bbad6eb 100644 --- a/js/js.translator/testData/lineNumbers/inlineLocalVarsRef.kt +++ b/js/js.translator/testData/lineNumbers/inlineLocalVarsRef.kt @@ -10,4 +10,4 @@ fun bar() { } // LINES(JS): 1 1 1 1 1 6 2 2 3 3 4 4 8 10 2 2 9 2 3 3 4 4 -// LINES(JS_IR): 1 1 2 3 3 3 4 4 8 8 * 2 3 3 3 4 4 +// LINES(JS_IR): 1 1 2 3 3 3 4 4 8 8 * 2 9 2 3 3 3 4 4 \ No newline at end of file diff --git a/js/js.translator/testData/lineNumbers/inlineMultiModule/simple.kt b/js/js.translator/testData/lineNumbers/inlineMultiModule/simple.kt index 972872347e2..a07a346951b 100644 --- a/js/js.translator/testData/lineNumbers/inlineMultiModule/simple.kt +++ b/js/js.translator/testData/lineNumbers/inlineMultiModule/simple.kt @@ -22,5 +22,5 @@ fun box() { foo("42") } -// LINES(JS): 6 20 23 7 7 21 7 8 8 21 8 7 7 22 7 8 8 22 8 -// LINES(JS_IR): 20 20 * 7 7 8 8 * 7 7 8 8 +// LINES(JS): 6 20 23 7 7 21 7 8 8 21 8 7 7 22 7 8 8 22 8 +// LINES(JS_IR): 20 20 * 7 7 8 7 8 8 * 7 7 8 7 8 8 \ No newline at end of file diff --git a/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt b/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt index e8f3f624503..5169a34f02e 100644 --- a/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt +++ b/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt @@ -1110,7 +1110,7 @@ public actual fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1126,7 +1126,7 @@ public actual fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1142,7 +1142,7 @@ public actual fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun ShortArray.fill(element: Short, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1158,7 +1158,7 @@ public actual fun ShortArray.fill(element: Short, fromIndex: Int = 0, toIndex: I @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun IntArray.fill(element: Int, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1174,7 +1174,7 @@ public actual fun IntArray.fill(element: Int, fromIndex: Int = 0, toIndex: Int = @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun LongArray.fill(element: Long, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1190,7 +1190,7 @@ public actual fun LongArray.fill(element: Long, fromIndex: Int = 0, toIndex: Int @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun FloatArray.fill(element: Float, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1206,7 +1206,7 @@ public actual fun FloatArray.fill(element: Float, fromIndex: Int = 0, toIndex: I @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun DoubleArray.fill(element: Double, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1222,7 +1222,7 @@ public actual fun DoubleArray.fill(element: Double, fromIndex: Int = 0, toIndex: @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun BooleanArray.fill(element: Boolean, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1238,7 +1238,8 @@ public actual fun BooleanArray.fill(element: Boolean, fromIndex: Int = 0, toInde @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun CharArray.fill(element: Char, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + // We need to call [Char.code] here to eliminate Char-boxing with the new JS function inlining logic + nativeFill(element.code, fromIndex, toIndex) } /** diff --git a/libraries/stdlib/js/src/generated/_ArraysJs.kt b/libraries/stdlib/js/src/generated/_ArraysJs.kt index 2140ac0cbc3..1b4c3b51df1 100644 --- a/libraries/stdlib/js/src/generated/_ArraysJs.kt +++ b/libraries/stdlib/js/src/generated/_ArraysJs.kt @@ -1140,7 +1140,7 @@ public actual fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1156,7 +1156,7 @@ public actual fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1172,7 +1172,7 @@ public actual fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun ShortArray.fill(element: Short, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1188,7 +1188,7 @@ public actual fun ShortArray.fill(element: Short, fromIndex: Int = 0, toIndex: I @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun IntArray.fill(element: Int, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1204,7 +1204,7 @@ public actual fun IntArray.fill(element: Int, fromIndex: Int = 0, toIndex: Int = @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun LongArray.fill(element: Long, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1220,7 +1220,7 @@ public actual fun LongArray.fill(element: Long, fromIndex: Int = 0, toIndex: Int @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun FloatArray.fill(element: Float, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1236,7 +1236,7 @@ public actual fun FloatArray.fill(element: Float, fromIndex: Int = 0, toIndex: I @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun DoubleArray.fill(element: Double, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1252,7 +1252,7 @@ public actual fun DoubleArray.fill(element: Double, fromIndex: Int = 0, toIndex: @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun BooleanArray.fill(element: Boolean, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) } /** @@ -1268,7 +1268,8 @@ public actual fun BooleanArray.fill(element: Boolean, fromIndex: Int = 0, toInde @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun CharArray.fill(element: Char, fromIndex: Int = 0, toIndex: Int = size): Unit { AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + // We need to call [Char.code] here to eliminate Char-boxing with the new JS function inlining logic + nativeFill(element.code, fromIndex, toIndex) } /** diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index ac342016e64..79898740e5b 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -1623,9 +1623,20 @@ object ArrayOps : TemplateGroupBase() { body { """ AbstractList.checkRangeIndexes(fromIndex, toIndex, size) - nativeFill(element, fromIndex, toIndex); + nativeFill(element, fromIndex, toIndex) """ } + specialFor(ArraysOfPrimitives) { + if (primitive == PrimitiveType.Char) { + body { + """ + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + // We need to call [Char.code] here to eliminate Char-boxing with the new JS function inlining logic + nativeFill(element.code, fromIndex, toIndex) + """ + } + } + } } on(Platform.Native) { suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")