JS: fix suspend lambda inlining
* Also avoid casts when setting inline metadata
This commit is contained in:
+5
@@ -893,6 +893,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/coroutines/debugStatement.kt");
|
runTest("js/js.translator/testData/box/coroutines/debugStatement.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineLambdaNonLocalReturn.kt")
|
||||||
|
public void testInlineLambdaNonLocalReturn() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/inlineLambdaNonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localVarOptimization.kt")
|
@TestMetadata("localVarOptimization.kt")
|
||||||
public void testLocalVarOptimization() throws Exception {
|
public void testLocalVarOptimization() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/coroutines/localVarOptimization.kt");
|
runTest("js/js.translator/testData/box/coroutines/localVarOptimization.kt");
|
||||||
|
|||||||
+5
@@ -893,6 +893,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/coroutines/debugStatement.kt");
|
runTest("js/js.translator/testData/box/coroutines/debugStatement.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineLambdaNonLocalReturn.kt")
|
||||||
|
public void testInlineLambdaNonLocalReturn() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/inlineLambdaNonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localVarOptimization.kt")
|
@TestMetadata("localVarOptimization.kt")
|
||||||
public void testLocalVarOptimization() throws Exception {
|
public void testLocalVarOptimization() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/coroutines/localVarOptimization.kt");
|
runTest("js/js.translator/testData/box/coroutines/localVarOptimization.kt");
|
||||||
|
|||||||
+4
-5
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.js.translate.callTranslator
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
@@ -109,7 +111,7 @@ private fun translateCall(
|
|||||||
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||||
assert(explicitReceivers.extensionReceiver == null) { "VariableAsFunctionResolvedCall must have one receiver" }
|
assert(explicitReceivers.extensionReceiver == null) { "VariableAsFunctionResolvedCall must have one receiver" }
|
||||||
val variableCall = resolvedCall.variableCall
|
val variableCall = resolvedCall.variableCall
|
||||||
val isFunctionType = variableCall.resultingDescriptor.type.isFunctionTypeOrSubtype
|
val isFunctionType = variableCall.resultingDescriptor.type.run { isFunctionTypeOrSubtype || isSuspendFunctionTypeOrSubtype }
|
||||||
val inlineCall = if (isFunctionType) variableCall else resolvedCall
|
val inlineCall = if (isFunctionType) variableCall else resolvedCall
|
||||||
|
|
||||||
val newExplicitReceivers = if (variableCall.expectedReceivers()) {
|
val newExplicitReceivers = if (variableCall.expectedReceivers()) {
|
||||||
@@ -149,9 +151,7 @@ private fun translateFunctionCall(
|
|||||||
var callExpression = callInfo.translateFunctionCall()
|
var callExpression = callInfo.translateFunctionCall()
|
||||||
|
|
||||||
if (CallExpressionTranslator.shouldBeInlined(inlineResolvedCall.resultingDescriptor, context)) {
|
if (CallExpressionTranslator.shouldBeInlined(inlineResolvedCall.resultingDescriptor, context)) {
|
||||||
val callElement = resolvedCall.call.callElement
|
setInlineCallMetadata(callExpression, resolvedCall.call.callElement, inlineResolvedCall.resultingDescriptor, context)
|
||||||
val ktExpression = (callElement as? KtWhenConditionInRange)?.rangeExpression ?: callElement as KtExpression
|
|
||||||
setInlineCallMetadata(callExpression, ktExpression, inlineResolvedCall.resultingDescriptor, context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolvedCall.resultingDescriptor.isSuspend) {
|
if (resolvedCall.resultingDescriptor.isSuspend) {
|
||||||
@@ -171,7 +171,6 @@ private fun translateFunctionCall(
|
|||||||
return callExpression
|
return callExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun mayBeMarkByRangeMetadata(resolvedCall: ResolvedCall<out FunctionDescriptor>, callExpression: JsExpression) {
|
private fun mayBeMarkByRangeMetadata(resolvedCall: ResolvedCall<out FunctionDescriptor>, callExpression: JsExpression) {
|
||||||
when (resolvedCall.resultingDescriptor.fqNameSafe) {
|
when (resolvedCall.resultingDescriptor.fqNameSafe) {
|
||||||
intRangeToFqName -> {
|
intRangeToFqName -> {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
|||||||
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
|
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
|
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
||||||
|
|
||||||
@@ -40,10 +40,10 @@ import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
|||||||
* (x != null) ? fn.call(x, y) : null
|
* (x != null) ? fn.call(x, y) : null
|
||||||
*/
|
*/
|
||||||
fun setInlineCallMetadata(
|
fun setInlineCallMetadata(
|
||||||
expression: JsExpression,
|
expression: JsExpression,
|
||||||
psiElement: KtExpression,
|
psiElement: KtElement,
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
context: TranslationContext
|
context: TranslationContext
|
||||||
) {
|
) {
|
||||||
assert(CallExpressionTranslator.shouldBeInlined(descriptor)) {
|
assert(CallExpressionTranslator.shouldBeInlined(descriptor)) {
|
||||||
"Expected descriptor of callable, that should be inlined, but got: $descriptor"
|
"Expected descriptor of callable, that should be inlined, but got: $descriptor"
|
||||||
@@ -70,14 +70,14 @@ fun setInlineCallMetadata(
|
|||||||
|
|
||||||
fun setInlineCallMetadata(
|
fun setInlineCallMetadata(
|
||||||
expression: JsExpression,
|
expression: JsExpression,
|
||||||
psiElement: KtExpression,
|
psiElement: KtElement,
|
||||||
resolvedCall: ResolvedCall<*>,
|
resolvedCall: ResolvedCall<*>,
|
||||||
context: TranslationContext
|
context: TranslationContext
|
||||||
) = setInlineCallMetadata(expression, psiElement, PsiUtils.getFunctionDescriptor(resolvedCall), context)
|
) = setInlineCallMetadata(expression, psiElement, PsiUtils.getFunctionDescriptor(resolvedCall), context)
|
||||||
|
|
||||||
fun setInlineCallMetadata(
|
fun setInlineCallMetadata(
|
||||||
nameRef: JsNameRef,
|
nameRef: JsNameRef,
|
||||||
psiElement: KtExpression,
|
psiElement: KtElement,
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
context: TranslationContext
|
context: TranslationContext
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1305
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
|
suspend inline fun doTwice(block: suspend () -> Unit) {
|
||||||
|
block()
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
|
||||||
|
var testResult: String = ""
|
||||||
|
|
||||||
|
fun build(c: suspend () -> Unit) {
|
||||||
|
c.startCoroutine(Continuation<Unit>(EmptyCoroutineContext) { })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
build {
|
||||||
|
doTwice {
|
||||||
|
testResult += "OK"
|
||||||
|
return@build
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return testResult
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user