JS: coroutines: fix inlining of suspend functions

This commit is contained in:
Alexey Andreev
2016-11-21 16:44:56 +03:00
parent 8b9852edec
commit e44edf12e0
6 changed files with 30 additions and 36 deletions
@@ -1,5 +1,8 @@
// WITH_RUNTIME
// WITH_REFLECT
// CHECK_NOT_CALLED: suspendInline_die06n$
// CHECK_NOT_CALLED: suspendInline_nesahw$
// CHECK_NOT_CALLED: suspendInline_grpnnl$
class Controller {
fun withValue(v: String, x: Continuation<String>) {
x.resume(v)
@@ -27,9 +27,12 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.general.Translation
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.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.setInlineCallMetadata
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.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
@@ -96,32 +99,43 @@ private fun translateCall(context: TranslationContext,
if (resolvedCall is VariableAsFunctionResolvedCall) {
assert(explicitReceivers.extensionReceiver == null) { "VariableAsFunctionResolvedCall must have one receiver" }
val variableCall = resolvedCall.variableCall
if (variableCall.expectedReceivers()) {
return if (variableCall.expectedReceivers()) {
val newReceiver = CallTranslator.translateGet(context, variableCall, explicitReceivers.extensionOrDispatchReceiver)
return translateFunctionCall(context, resolvedCall.functionCall, ExplicitReceivers(newReceiver))
translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(newReceiver))
} else {
val dispatchReceiver = CallTranslator.translateGet(context, variableCall, null)
if (explicitReceivers.extensionOrDispatchReceiver == null)
return translateFunctionCall(context, resolvedCall.functionCall, ExplicitReceivers(dispatchReceiver))
else
return translateFunctionCall(context, resolvedCall.functionCall, ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver))
if (explicitReceivers.extensionOrDispatchReceiver == null) {
translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(dispatchReceiver))
}
else {
translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall,
ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver))
}
}
}
val call = resolvedCall.call
if (call.callType == CallType.INVOKE && !isInvokeCallOnVariable(call)) {
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,
resolvedCall: ResolvedCall<out FunctionDescriptor>,
inlineResolvedCall: ResolvedCall<out CallableDescriptor>,
explicitReceivers: ExplicitReceivers
): JsExpression {
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) {
context.currentBlock.statements += JsAstUtils.asSyntheticStatement((callExpression as JsInvocation).apply {
isSuspend = true
@@ -90,7 +90,7 @@ public class DestructuringDeclarationTranslator extends AbstractTranslator {
assert entryInitCall != null : "Entry init call must be not null";
JsExpression entryInitializer = CallTranslator.translate(context(), entryInitCall, multiObjNameRef);
FunctionDescriptor candidateDescriptor = entryInitCall.getCandidateDescriptor();
if (CallExpressionTranslator.shouldBeInlined(candidateDescriptor)) {
if (CallExpressionTranslator.shouldBeInlined(candidateDescriptor, context())) {
setInlineCallMetadata(entryInitializer, entry, entryInitCall, context());
}
@@ -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.TranslationContext;
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.psi.KtDeclarationWithBody;
import org.jetbrains.kotlin.psi.KtLambdaExpression;
@@ -107,7 +106,7 @@ public final class FunctionTranslator extends AbstractTranslator {
public JsExpression translateAsMethod() {
translateAsMethodWithoutMetadata();
if (shouldBeInlined(descriptor) && DescriptorUtilsKt.isEffectivelyPublicApi(descriptor)) {
if (shouldBeInlined(descriptor, context()) && DescriptorUtilsKt.isEffectivelyPublicApi(descriptor)) {
InlineMetadata metadata = InlineMetadata.compose(functionObject, descriptor);
return metadata.getFunctionWithMetadata();
}
@@ -36,8 +36,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import java.util.List;
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;
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
@@ -55,19 +53,12 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
return (new CallExpressionTranslator(expression, receiver, context)).translateJsCode();
}
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
if (shouldBeInlined(expression, context)) {
setInlineCallMetadata(callExpression, expression, resolvedCall, context);
}
return callExpression;
return (new CallExpressionTranslator(expression, receiver, context)).translate();
}
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;
CallableDescriptor descriptor = getFunctionDescriptor(expression, context);
return shouldBeInlined(descriptor);
}
@@ -20,11 +20,9 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.KtTokens;
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.VariableAsFunctionResolvedCall;
@@ -99,7 +97,7 @@ public final class PsiUtils {
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);
}
@@ -126,17 +124,6 @@ public final class PsiUtils {
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
public static CallableDescriptor getFunctionDescriptor(ResolvedCall<?> resolvedCall) {
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {