From dcb8b7b92c97ac3e887d10e51836916472ae29f9 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Mon, 16 Jan 2017 19:23:38 +0300 Subject: [PATCH] JS: fix inlining of callable references --- .../codegen/box/reflection/functions/simpleNames.kt | 3 --- .../js/backend/ast/metadata/metadataProperties.kt | 2 ++ .../js/inline/clean/RedundantStatementElimination.kt | 2 ++ .../kotlin/js/inline/context/FunctionContext.kt | 11 ++++++++++- .../js/test/semantics/JsCodegenBoxTestGenerated.java | 8 +------- .../reference/CallableReferenceTranslator.kt | 6 ++++++ .../box/inlineMultiModule/callableReference.kt | 2 +- .../inlineStdlib/callableRefToFunInCurrentModule.kt | 2 +- 8 files changed, 23 insertions(+), 13 deletions(-) diff --git a/compiler/testData/codegen/box/reflection/functions/simpleNames.kt b/compiler/testData/codegen/box/reflection/functions/simpleNames.kt index 46ce3d981ad..9df53d8ee51 100644 --- a/compiler/testData/codegen/box/reflection/functions/simpleNames.kt +++ b/compiler/testData/codegen/box/reflection/functions/simpleNames.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_REFLECT import kotlin.test.assertEquals 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 d1a3b8e9692..7cd5514548f 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 @@ -32,6 +32,8 @@ var JsName.descriptor: DeclarationDescriptor? by MetadataProperty(default = null // TODO: move this to module 'js.inliner' and change dependency on 'frontend' to dependency on 'descriptors' var JsInvocation.inlineStrategy: InlineStrategy? by MetadataProperty(default = null) +var JsInvocation.isCallableReference by MetadataProperty(default = false) + var JsInvocation.descriptor: CallableDescriptor? by MetadataProperty(default = null) var JsInvocation.psiElement: PsiElement? by MetadataProperty(default = null) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt index badd8a29413..adb2eee900f 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt @@ -190,6 +190,8 @@ class RedundantStatementElimination(private val root: JsFunction) { is JsObjectLiteral -> expression.propertyInitializers.flatMap { replace(it.labelExpr) + replace(it.valueExpr) } + is JsFunction -> if (expression.name == null) listOf() else listOf(expression) + else -> listOf(expression) } } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt index fb6e9b45211..c03138d5520 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.js.inline.context import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.metadata.isCallableReference import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor import org.jetbrains.kotlin.js.inline.FunctionReader import org.jetbrains.kotlin.js.inline.util.* @@ -91,7 +92,7 @@ abstract class FunctionContext( val qualifier = callQualifier.transitiveStaticRef return when (qualifier) { is JsInvocation -> { - getSimpleName(qualifier)?.let { simpleName -> + tryExtractCallableReference(qualifier) ?: getSimpleName(qualifier)?.let { simpleName -> lookUpStaticFunction(simpleName)?.let { if (isFunctionCreator(it)) it else null } } } @@ -100,4 +101,12 @@ abstract class FunctionContext( else -> null } } + + private fun tryExtractCallableReference(invocation: JsInvocation): JsFunction? { + if (invocation.isCallableReference) { + val arg = invocation.arguments[1] + if (arg is JsFunction) return arg + } + return null + } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index b772edfcf53..108a72580e2 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -16694,13 +16694,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("simpleNames.kt") public void testSimpleNames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/functions/simpleNames.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt index 328e444479a..5eeb286d841 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt @@ -22,6 +22,9 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind +import org.jetbrains.kotlin.js.backend.ast.metadata.isCallableReference +import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.TranslationContext @@ -226,7 +229,10 @@ object CallableReferenceTranslator { val nameLiteral = context.program().getStringLiteral(name) val invokeName = Namer.FUNCTION_CALLABLE_REF val invokeFun = JsNameRef(invokeName, Namer.kotlinObject()) + invokeFun.sideEffects = SideEffectKind.PURE val invocation = JsInvocation(invokeFun, nameLiteral, function) + invocation.isCallableReference = true + invocation.sideEffects = SideEffectKind.PURE return invocation } } diff --git a/js/js.translator/testData/box/inlineMultiModule/callableReference.kt b/js/js.translator/testData/box/inlineMultiModule/callableReference.kt index 3c942097ae4..95cb44ee80e 100644 --- a/js/js.translator/testData/box/inlineMultiModule/callableReference.kt +++ b/js/js.translator/testData/box/inlineMultiModule/callableReference.kt @@ -14,7 +14,7 @@ import utils.* // CHECK_CONTAINS_NO_CALLS: test except=imul -internal fun multiplyBy2(x: Int): Int = x * 2 +internal inline fun multiplyBy2(x: Int): Int = x * 2 internal fun test(x: Int): Int = apply(x, ::multiplyBy2) diff --git a/js/js.translator/testData/box/inlineStdlib/callableRefToFunInCurrentModule.kt b/js/js.translator/testData/box/inlineStdlib/callableRefToFunInCurrentModule.kt index 818e656b180..9247ae2dcd7 100644 --- a/js/js.translator/testData/box/inlineStdlib/callableRefToFunInCurrentModule.kt +++ b/js/js.translator/testData/box/inlineStdlib/callableRefToFunInCurrentModule.kt @@ -3,7 +3,7 @@ package foo // CHECK_NOT_CALLED_IN_SCOPE: scope=test function=even // CHECK_NOT_CALLED_IN_SCOPE: scope=test function=filter_azvtw4$ -internal fun even(x: Int) = x % 2 == 0 +internal inline fun even(x: Int) = x % 2 == 0 internal fun test(a: List) = a.filter(::even)