JS: coroutines: fix inlining of suspend functions
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
// CHECK_NOT_CALLED: suspendInline_die06n$
|
||||||
|
// CHECK_NOT_CALLED: suspendInline_nesahw$
|
||||||
|
// CHECK_NOT_CALLED: suspendInline_grpnnl$
|
||||||
class Controller {
|
class Controller {
|
||||||
fun withValue(v: String, x: Continuation<String>) {
|
fun withValue(v: String, x: Continuation<String>) {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
|||||||
+22
-8
@@ -27,9 +27,12 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
||||||
|
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.setInlineCallMetadata
|
||||||
import org.jetbrains.kotlin.psi.Call.CallType
|
import org.jetbrains.kotlin.psi.Call.CallType
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
|
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||||
@@ -96,32 +99,43 @@ private fun translateCall(context: TranslationContext,
|
|||||||
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
|
||||||
if (variableCall.expectedReceivers()) {
|
|
||||||
|
return if (variableCall.expectedReceivers()) {
|
||||||
val newReceiver = CallTranslator.translateGet(context, variableCall, explicitReceivers.extensionOrDispatchReceiver)
|
val newReceiver = CallTranslator.translateGet(context, variableCall, explicitReceivers.extensionOrDispatchReceiver)
|
||||||
return translateFunctionCall(context, resolvedCall.functionCall, ExplicitReceivers(newReceiver))
|
translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(newReceiver))
|
||||||
} else {
|
} else {
|
||||||
val dispatchReceiver = CallTranslator.translateGet(context, variableCall, null)
|
val dispatchReceiver = CallTranslator.translateGet(context, variableCall, null)
|
||||||
if (explicitReceivers.extensionOrDispatchReceiver == null)
|
if (explicitReceivers.extensionOrDispatchReceiver == null) {
|
||||||
return translateFunctionCall(context, resolvedCall.functionCall, ExplicitReceivers(dispatchReceiver))
|
translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(dispatchReceiver))
|
||||||
else
|
}
|
||||||
return translateFunctionCall(context, resolvedCall.functionCall, ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver))
|
else {
|
||||||
|
translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall,
|
||||||
|
ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val call = resolvedCall.call
|
val call = resolvedCall.call
|
||||||
if (call.callType == CallType.INVOKE && !isInvokeCallOnVariable(call)) {
|
if (call.callType == CallType.INVOKE && !isInvokeCallOnVariable(call)) {
|
||||||
val explicitReceiversForInvoke = computeExplicitReceiversForInvoke(context, resolvedCall, explicitReceivers)
|
val explicitReceiversForInvoke = computeExplicitReceiversForInvoke(context, resolvedCall, explicitReceivers)
|
||||||
return translateFunctionCall(context, resolvedCall, explicitReceiversForInvoke)
|
return translateFunctionCall(context, resolvedCall, resolvedCall, explicitReceiversForInvoke)
|
||||||
}
|
}
|
||||||
|
|
||||||
return translateFunctionCall(context, resolvedCall, explicitReceivers)
|
return translateFunctionCall(context, resolvedCall, resolvedCall, explicitReceivers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateFunctionCall(context: TranslationContext,
|
private fun translateFunctionCall(context: TranslationContext,
|
||||||
resolvedCall: ResolvedCall<out FunctionDescriptor>,
|
resolvedCall: ResolvedCall<out FunctionDescriptor>,
|
||||||
|
inlineResolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||||
explicitReceivers: ExplicitReceivers
|
explicitReceivers: ExplicitReceivers
|
||||||
): JsExpression {
|
): JsExpression {
|
||||||
val callExpression = context.getCallInfo(resolvedCall, explicitReceivers).translateFunctionCall()
|
val callExpression = context.getCallInfo(resolvedCall, explicitReceivers).translateFunctionCall()
|
||||||
|
|
||||||
|
if (CallExpressionTranslator.shouldBeInlined(inlineResolvedCall.resultingDescriptor, context)) {
|
||||||
|
setInlineCallMetadata(callExpression, resolvedCall.call.callElement as KtExpression,
|
||||||
|
inlineResolvedCall.resultingDescriptor, context)
|
||||||
|
}
|
||||||
|
|
||||||
if (resolvedCall.resultingDescriptor.isSuspend && resolvedCall.resultingDescriptor.initialSignatureDescriptor != null) {
|
if (resolvedCall.resultingDescriptor.isSuspend && resolvedCall.resultingDescriptor.initialSignatureDescriptor != null) {
|
||||||
context.currentBlock.statements += JsAstUtils.asSyntheticStatement((callExpression as JsInvocation).apply {
|
context.currentBlock.statements += JsAstUtils.asSyntheticStatement((callExpression as JsInvocation).apply {
|
||||||
isSuspend = true
|
isSuspend = true
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ public class DestructuringDeclarationTranslator extends AbstractTranslator {
|
|||||||
assert entryInitCall != null : "Entry init call must be not null";
|
assert entryInitCall != null : "Entry init call must be not null";
|
||||||
JsExpression entryInitializer = CallTranslator.translate(context(), entryInitCall, multiObjNameRef);
|
JsExpression entryInitializer = CallTranslator.translate(context(), entryInitCall, multiObjNameRef);
|
||||||
FunctionDescriptor candidateDescriptor = entryInitCall.getCandidateDescriptor();
|
FunctionDescriptor candidateDescriptor = entryInitCall.getCandidateDescriptor();
|
||||||
if (CallExpressionTranslator.shouldBeInlined(candidateDescriptor)) {
|
if (CallExpressionTranslator.shouldBeInlined(candidateDescriptor, context())) {
|
||||||
setInlineCallMetadata(entryInitializer, entry, entryInitCall, context());
|
setInlineCallMetadata(entryInitializer, entry, entryInitCall, context());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.js.translate.context.AliasingContext;
|
|||||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||||
@@ -107,7 +106,7 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
public JsExpression translateAsMethod() {
|
public JsExpression translateAsMethod() {
|
||||||
translateAsMethodWithoutMetadata();
|
translateAsMethodWithoutMetadata();
|
||||||
|
|
||||||
if (shouldBeInlined(descriptor) && DescriptorUtilsKt.isEffectivelyPublicApi(descriptor)) {
|
if (shouldBeInlined(descriptor, context()) && DescriptorUtilsKt.isEffectivelyPublicApi(descriptor)) {
|
||||||
InlineMetadata metadata = InlineMetadata.compose(functionObject, descriptor);
|
InlineMetadata metadata = InlineMetadata.compose(functionObject, descriptor);
|
||||||
return metadata.getFunctionWithMetadata();
|
return metadata.getFunctionWithMetadata();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-11
@@ -36,8 +36,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.resolve.diagnostics.JsCallChecker.isJsCall;
|
import static org.jetbrains.kotlin.js.resolve.diagnostics.JsCallChecker.isJsCall;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.InlineUtils.setInlineCallMetadata;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getFunctionDescriptor;
|
|
||||||
import static org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator.getConstant;
|
import static org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator.getConstant;
|
||||||
|
|
||||||
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
|
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
|
||||||
@@ -55,19 +53,12 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
|||||||
return (new CallExpressionTranslator(expression, receiver, context)).translateJsCode();
|
return (new CallExpressionTranslator(expression, receiver, context)).translateJsCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
|
return (new CallExpressionTranslator(expression, receiver, context)).translate();
|
||||||
|
|
||||||
if (shouldBeInlined(expression, context)) {
|
|
||||||
setInlineCallMetadata(callExpression, expression, resolvedCall, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return callExpression;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldBeInlined(@NotNull KtCallExpression expression, @NotNull TranslationContext context) {
|
public static boolean shouldBeInlined(@NotNull CallableDescriptor descriptor, @NotNull TranslationContext context) {
|
||||||
if (context.getConfig().getConfiguration().getBoolean(CommonConfigurationKeys.DISABLE_INLINE)) return false;
|
if (context.getConfig().getConfiguration().getBoolean(CommonConfigurationKeys.DISABLE_INLINE)) return false;
|
||||||
|
|
||||||
CallableDescriptor descriptor = getFunctionDescriptor(expression, context);
|
|
||||||
return shouldBeInlined(descriptor);
|
return shouldBeInlined(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ import com.intellij.psi.tree.IElementType;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
|
||||||
import org.jetbrains.kotlin.lexer.KtToken;
|
import org.jetbrains.kotlin.lexer.KtToken;
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||||
|
|
||||||
@@ -99,7 +97,7 @@ public final class PsiUtils {
|
|||||||
return isInOperation(binaryExpression) || isNotInOperation(binaryExpression);
|
return isInOperation(binaryExpression) || isNotInOperation(binaryExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNotInOperation(@NotNull KtBinaryExpression binaryExpression) {
|
private static boolean isNotInOperation(@NotNull KtBinaryExpression binaryExpression) {
|
||||||
return (binaryExpression.getOperationToken() == KtTokens.NOT_IN);
|
return (binaryExpression.getOperationToken() == KtTokens.NOT_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,17 +124,6 @@ public final class PsiUtils {
|
|||||||
return rangeExpression;
|
return rangeExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static CallableDescriptor getFunctionDescriptor(
|
|
||||||
@NotNull KtCallExpression expression,
|
|
||||||
@NotNull TranslationContext context
|
|
||||||
) {
|
|
||||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, context.bindingContext());
|
|
||||||
assert resolvedCall != null;
|
|
||||||
|
|
||||||
return getFunctionDescriptor(resolvedCall);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CallableDescriptor getFunctionDescriptor(ResolvedCall<?> resolvedCall) {
|
public static CallableDescriptor getFunctionDescriptor(ResolvedCall<?> resolvedCall) {
|
||||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||||
|
|||||||
Reference in New Issue
Block a user