JS: fix inlining of callable references

This commit is contained in:
Alexey Andreev
2017-01-16 19:23:38 +03:00
parent 7a0f75f164
commit dcb8b7b92c
8 changed files with 23 additions and 13 deletions
@@ -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
@@ -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)
@@ -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)
}
}
@@ -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
}
}
@@ -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);
}
}
@@ -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
}
}
@@ -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)
@@ -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<Int>) = a.filter(::even)