JS: simplify how suspend functions inlined
This commit is contained in:
+1
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import kotlin.coroutines.*
|
||||
|
||||
@@ -73,18 +73,6 @@ var HasMetadata.sideEffects: SideEffectKind by MetadataProperty(default = SideEf
|
||||
*/
|
||||
var JsInvocation.isSuspend: Boolean by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a pre-suspend call-site that is to be processed by coroutine transformer.
|
||||
* For normal suspend call-sites both [isSuspend] and [isPreSuspend] present.
|
||||
* For inlined suspend calls fake calls are generated before and after inlined function body.
|
||||
*/
|
||||
var JsInvocation.isPreSuspend: Boolean by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a fake suspend call for inlining purposes.
|
||||
*/
|
||||
var JsInvocation.isFakeSuspend: Boolean by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a reference to coroutine's `result` field that contains result of
|
||||
* last suspended invocation.
|
||||
|
||||
@@ -14,5 +14,6 @@
|
||||
<orderEntry type="module" module-name="js.parser" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="backend-common" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -17,7 +17,10 @@
|
||||
package org.jetbrains.kotlin.js.coroutine
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.inline.util.collectBreakContinueTargets
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
@@ -35,7 +38,6 @@ class CoroutineBodyTransformer(private val program: JsProgram, private val conte
|
||||
private lateinit var nodesToSplit: Set<JsNode>
|
||||
private var currentCatchBlock = globalCatchBlock
|
||||
private val tryStack = mutableListOf(TryBlock(globalCatchBlock, null))
|
||||
private var suspendTarget: CoroutineBlock? = null
|
||||
|
||||
var hasFinallyBlocks = false
|
||||
get
|
||||
@@ -331,45 +333,39 @@ class CoroutineBodyTransformer(private val program: JsProgram, private val conte
|
||||
|
||||
private fun handleExpression(expression: JsExpression): JsExpression? {
|
||||
return if (expression is JsInvocation) {
|
||||
var result: JsExpression? = expression
|
||||
if (expression.isPreSuspend) {
|
||||
result = handlePreSuspend(expression)
|
||||
}
|
||||
if (expression.isSuspend) {
|
||||
handleSuspend(expression)
|
||||
result = null
|
||||
}
|
||||
result
|
||||
if (handleInvocation(expression)) null else expression
|
||||
}
|
||||
else {
|
||||
val assignment = JsAstUtils.decomposeAssignment(expression)
|
||||
if (assignment != null) {
|
||||
(assignment.second as? JsInvocation)?.let { return if (handleInvocation(it)) null else expression }
|
||||
}
|
||||
expression
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePreSuspend(invocation: JsInvocation): JsExpression? {
|
||||
val nextBlock = CoroutineBlock()
|
||||
currentStatements += state(nextBlock)
|
||||
suspendTarget = nextBlock
|
||||
|
||||
return if (invocation.isFakeSuspend) null else invocation
|
||||
private fun handleInvocation(expression: JsInvocation): Boolean {
|
||||
return if (expression.isSuspend) {
|
||||
handleSuspend(expression)
|
||||
true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSuspend(invocation: JsInvocation) {
|
||||
val invokeExpression = if (invocation.isFakeSuspend) invocation.arguments.getOrNull(0) else invocation
|
||||
val statements = if (invokeExpression == null) {
|
||||
listOf(JsReturn(context.metadata.suspendObjectRef.deepCopy()))
|
||||
val nextBlock = CoroutineBlock()
|
||||
currentStatements += state(nextBlock)
|
||||
|
||||
val resultRef = JsNameRef(context.metadata.resultName, JsAstUtils.stateMachineReceiver()).apply {
|
||||
sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||
}
|
||||
else {
|
||||
val resultRef = JsNameRef(context.metadata.resultName, JsAstUtils.stateMachineReceiver()).apply {
|
||||
sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||
}
|
||||
val invocationStatement = JsAstUtils.assignment(resultRef, invokeExpression).makeStmt()
|
||||
val suspendCondition = JsAstUtils.equality(resultRef.deepCopy(), context.metadata.suspendObjectRef.deepCopy())
|
||||
val suspendIfNeeded = JsIf(suspendCondition, JsReturn(context.metadata.suspendObjectRef.deepCopy()))
|
||||
listOf(invocationStatement, suspendIfNeeded, JsBreak())
|
||||
}
|
||||
currentStatements += statements
|
||||
currentBlock = suspendTarget!!
|
||||
val invocationStatement = JsAstUtils.assignment(resultRef, invocation).makeStmt()
|
||||
val suspendCondition = JsAstUtils.equality(resultRef.deepCopy(), context.metadata.suspendObjectRef.deepCopy())
|
||||
val suspendIfNeeded = JsIf(suspendCondition, JsReturn(context.metadata.suspendObjectRef.deepCopy()))
|
||||
currentStatements += listOf(invocationStatement, suspendIfNeeded, JsBreak())
|
||||
currentBlock = nextBlock
|
||||
}
|
||||
|
||||
private fun state(target: CoroutineBlock): List<JsStatement> {
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
package org.jetbrains.kotlin.js.inline
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.inline.clean.removeDefaultInitializers
|
||||
import org.jetbrains.kotlin.js.inline.clean.removeFakeSuspend
|
||||
import org.jetbrains.kotlin.js.inline.context.InliningContext
|
||||
import org.jetbrains.kotlin.js.inline.context.NamingContext
|
||||
import org.jetbrains.kotlin.js.inline.util.*
|
||||
import org.jetbrains.kotlin.js.inline.util.rewriters.ReturnReplacingVisitor
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
|
||||
class FunctionInlineMutator
|
||||
private constructor(
|
||||
@@ -32,7 +31,7 @@ private constructor(
|
||||
private val inliningContext: InliningContext
|
||||
) {
|
||||
private val invokedFunction: JsFunction
|
||||
private val namingContext: NamingContext
|
||||
private val namingContext = inliningContext.newNamingContext()
|
||||
private val body: JsBlock
|
||||
private var resultExpr: JsExpression? = null
|
||||
private var resultName: JsName? = null
|
||||
@@ -40,23 +39,12 @@ private constructor(
|
||||
private val currentStatement = inliningContext.statementContext.currentNode
|
||||
|
||||
init {
|
||||
namingContext = inliningContext.newNamingContext()
|
||||
val functionContext = inliningContext.functionContext
|
||||
invokedFunction = uncoverClosure(functionContext.getFunctionDefinition(call).deepCopy())
|
||||
|
||||
// Removing fakeSuspend is not just an optimization.
|
||||
// Reentrant suspends are not supported by coroutine transformers.
|
||||
body = if (call.isSuspend) invokedFunction.body.removeFakeSuspend() else invokedFunction.body
|
||||
body = invokedFunction.body
|
||||
}
|
||||
|
||||
private fun process() {
|
||||
if (call.isSuspend) {
|
||||
val fakeSuspendCall = JsInvocation(JsAstUtils.pureFqn("fakeSuspend", JsAstUtils.pureFqn("Kotlin", null)))
|
||||
fakeSuspendCall.isPreSuspend = true
|
||||
fakeSuspendCall.isFakeSuspend = true
|
||||
body.statements.add(0, JsAstUtils.asSyntheticStatement(fakeSuspendCall))
|
||||
}
|
||||
|
||||
val arguments = getArguments()
|
||||
val parameters = getParameters()
|
||||
|
||||
@@ -125,10 +113,6 @@ private constructor(
|
||||
|
||||
val visitor = ReturnReplacingVisitor(resultExpr as? JsNameRef, breakName.makeRef(), invokedFunction, call.isSuspend)
|
||||
visitor.accept(body)
|
||||
|
||||
visitor.makeFakeSuspendCall(null)?.let { fakeSuspend ->
|
||||
body.statements += JsAstUtils.asSyntheticStatement(fakeSuspend)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getResultReference(): JsNameRef? {
|
||||
|
||||
@@ -20,7 +20,10 @@ import com.intellij.psi.PsiElement;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CommonCoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
@@ -180,6 +183,12 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
}
|
||||
|
||||
private void inline(@NotNull JsInvocation call, @NotNull JsContext context) {
|
||||
DeclarationDescriptor callDescriptor = MetadataProperties.getDescriptor(call);
|
||||
if (isSuspendWithCurrentContinuation(callDescriptor)) {
|
||||
inlineSuspendWithCurrentContinuation(call, context);
|
||||
return;
|
||||
}
|
||||
|
||||
JsInliningContext inliningContext = getInliningContext();
|
||||
InlineableResult inlineableResult = getInlineableCallReplacement(call, inliningContext);
|
||||
|
||||
@@ -205,6 +214,22 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
context.replaceMe(resultExpression);
|
||||
}
|
||||
|
||||
private static boolean isSuspendWithCurrentContinuation(@Nullable DeclarationDescriptor descriptor) {
|
||||
if (!(descriptor instanceof FunctionDescriptor)) return false;
|
||||
return CommonCoroutineCodegenUtilKt.isBuiltInSuspendCoroutineOrReturn((FunctionDescriptor) descriptor.getOriginal());
|
||||
}
|
||||
|
||||
private void inlineSuspendWithCurrentContinuation(@NotNull JsInvocation call, @NotNull JsContext context) {
|
||||
JsInliningContext inliningContext = getInliningContext();
|
||||
JsFunction containingFunction = inliningContext.function;
|
||||
JsExpression lambda = call.getArguments().get(0);
|
||||
JsParameter continuationParam = containingFunction.getParameters().get(containingFunction.getParameters().size() - 1);
|
||||
|
||||
JsInvocation invocation = new JsInvocation(lambda, continuationParam.getName().makeRef());
|
||||
MetadataProperties.setSuspend(invocation, true);
|
||||
context.replaceMe(accept(invocation));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsInliningContext getInliningContext() {
|
||||
return inliningContexts.peek();
|
||||
@@ -250,7 +275,11 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
private class JsInliningContext implements InliningContext {
|
||||
private final FunctionContext functionContext;
|
||||
|
||||
JsInliningContext(JsFunction function) {
|
||||
@NotNull
|
||||
public final JsFunction function;
|
||||
|
||||
JsInliningContext(@NotNull JsFunction function) {
|
||||
this.function = function;
|
||||
functionContext = new FunctionContext(function, functionReader) {
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -563,7 +563,7 @@ internal class TemporaryVariableElimination(private val function: JsFunction) {
|
||||
val name = x.name
|
||||
if (name != null && x.qualifier == null && name in namesToSubstitute) {
|
||||
val replacement = accept(definedValues[name]!!)
|
||||
ctx.replaceMe(replacement.apply { synthetic = true })
|
||||
ctx.replaceMe(replacement.deepCopy().apply { synthetic = true })
|
||||
return false
|
||||
}
|
||||
return super.visit(x, ctx)
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.inline.clean
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isFakeSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isPreSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
|
||||
fun <T : JsNode> T.removeFakeSuspend(): T {
|
||||
val visitor = object : JsVisitorWithContextImpl() {
|
||||
override fun endVisit(x: JsInvocation, ctx: JsContext<in JsNode>) {
|
||||
if (x.isFakeSuspend) {
|
||||
ctx.replaceMe(x.arguments.getOrElse(0) { Namer.getUndefinedExpression() })
|
||||
}
|
||||
else {
|
||||
x.isSuspend = false
|
||||
x.isPreSuspend = false
|
||||
}
|
||||
super.endVisit(x, ctx)
|
||||
}
|
||||
|
||||
override fun visit(x: JsExpressionStatement, ctx: JsContext<*>): Boolean {
|
||||
val expression = x.expression
|
||||
if (expression is JsInvocation && expression.isFakeSuspend && expression.arguments.isEmpty()) {
|
||||
x.synthetic = true
|
||||
}
|
||||
return super.visit(x, ctx)
|
||||
}
|
||||
}
|
||||
return visitor.accept(this)
|
||||
}
|
||||
@@ -34,7 +34,7 @@ fun aliasArgumentsIfNeeded(
|
||||
|
||||
val replacement = context.getFreshName(paramName).apply {
|
||||
staticRef = arg
|
||||
context.newVar(this, arg)
|
||||
context.newVar(this, arg.deepCopy())
|
||||
}.makeRef()
|
||||
|
||||
context.replaceName(paramName, replacement)
|
||||
|
||||
+2
-4
@@ -21,10 +21,8 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) : JsVisitorWithContextImpl() {
|
||||
|
||||
override fun endVisit(x: JsNameRef, ctx: JsContext<JsNode>) {
|
||||
val replacement = replaceMap[x.name]
|
||||
if (replacement == null) return
|
||||
|
||||
ctx.replaceMe(replacement)
|
||||
val replacement = replaceMap[x.name] ?: return
|
||||
ctx.replaceMe(replacement.deepCopy())
|
||||
}
|
||||
|
||||
override fun endVisit(x: JsVars.JsVar, ctx: JsContext<JsNode>) {
|
||||
|
||||
+7
-12
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.inline.util.rewriters
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
|
||||
class ReturnReplacingVisitor(
|
||||
@@ -55,25 +56,19 @@ class ReturnReplacingVisitor(
|
||||
private fun getReturnReplacement(returnExpression: JsExpression?): JsExpression? {
|
||||
return if (returnExpression != null) {
|
||||
val assignment = resultRef?.let { lhs ->
|
||||
val rhs = makeFakeSuspendCall(returnExpression)!!
|
||||
val rhs = processCoroutineResult(returnExpression)!!
|
||||
JsAstUtils.assignment(lhs, rhs).apply { synthetic = true }
|
||||
}
|
||||
assignment ?: makeFakeSuspendCall(returnExpression)
|
||||
assignment ?: processCoroutineResult(returnExpression)
|
||||
}
|
||||
else {
|
||||
makeFakeSuspendCall(null)
|
||||
processCoroutineResult(null)
|
||||
}
|
||||
}
|
||||
|
||||
fun makeFakeSuspendCall(expression: JsExpression?): JsExpression? {
|
||||
fun processCoroutineResult(expression: JsExpression?): JsExpression? {
|
||||
if (!isSuspend) return expression
|
||||
|
||||
val fakeSuspendCall = JsInvocation(JsAstUtils.pureFqn("fakeSuspend", JsAstUtils.pureFqn("Kotlin", null)))
|
||||
fakeSuspendCall.isSuspend = true
|
||||
fakeSuspendCall.isFakeSuspend = true
|
||||
if (expression != null) {
|
||||
fakeSuspendCall.arguments += expression
|
||||
}
|
||||
return fakeSuspendCall
|
||||
val lhs = JsNameRef("\$\$coroutineResult\$\$", JsAstUtils.stateMachineReceiver()).apply { coroutineResult = true }
|
||||
return JsAstUtils.assignment(lhs, expression ?: Namer.getUndefinedExpression())
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -5795,7 +5795,13 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("dispatchResume.kt")
|
||||
public void testDispatchResume() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/dispatchResume.kt");
|
||||
doTest(fileName);
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("handleException.kt")
|
||||
|
||||
+8
-23
@@ -16,18 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.callTranslator
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineOrReturn
|
||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineResult
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
||||
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.reference.ReferenceTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.*
|
||||
import org.jetbrains.kotlin.psi.Call.CallType
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
@@ -35,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariabl
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
|
||||
@@ -128,11 +130,6 @@ private fun translateFunctionCall(
|
||||
inlineResolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
explicitReceivers: ExplicitReceivers
|
||||
): JsExpression {
|
||||
val descriptorToCall = resolvedCall.resultingDescriptor
|
||||
if (descriptorToCall is FunctionDescriptor && descriptorToCall.original.isBuiltInSuspendCoroutineOrReturn()) {
|
||||
return translateCallWithContinuation(context, resolvedCall)
|
||||
}
|
||||
|
||||
val callExpression = context.getCallInfo(resolvedCall, explicitReceivers).translateFunctionCall()
|
||||
|
||||
if (CallExpressionTranslator.shouldBeInlined(inlineResolvedCall.resultingDescriptor, context)) {
|
||||
@@ -141,10 +138,7 @@ private fun translateFunctionCall(
|
||||
}
|
||||
|
||||
if (resolvedCall.resultingDescriptor.isSuspend && context.isInStateMachine) {
|
||||
context.currentBlock.statements += JsAstUtils.asSyntheticStatement((callExpression as JsInvocation).apply {
|
||||
isSuspend = true
|
||||
isPreSuspend = true
|
||||
})
|
||||
context.currentBlock.statements += JsAstUtils.asSyntheticStatement((callExpression as JsInvocation).apply { isSuspend = true })
|
||||
val coroutineRef = TranslationUtils.translateContinuationArgument(context, resolvedCall)
|
||||
return context.defineTemporary(JsNameRef("\$\$coroutineResult\$\$", coroutineRef).apply {
|
||||
sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||
@@ -157,15 +151,6 @@ private fun translateFunctionCall(
|
||||
private val TranslationContext.isInStateMachine
|
||||
get() = (declarationDescriptor as? FunctionDescriptor)?.requiresStateMachineTransformation(this) == true
|
||||
|
||||
private fun translateCallWithContinuation(context: TranslationContext, resolvedCall: ResolvedCall<out FunctionDescriptor>): JsExpression {
|
||||
val arguments = CallArgumentTranslator.translate(resolvedCall, null, context)
|
||||
val coroutineArgument = TranslationUtils.getEnclosingContinuationParameter(context)
|
||||
val invocation = JsInvocation(arguments.valueArguments[0], ReferenceTranslator.translateAsValueReference(coroutineArgument, context))
|
||||
invocation.inlineStrategy = InlineStrategy.IN_PLACE
|
||||
context.currentBlock.statements += JsReturn(invocation)
|
||||
return JsLiteral.NULL
|
||||
}
|
||||
|
||||
fun computeExplicitReceiversForInvoke(
|
||||
context: TranslationContext,
|
||||
resolvedCall: ResolvedCall<out FunctionDescriptor>,
|
||||
|
||||
+2
-1
@@ -75,7 +75,8 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
|
||||
if (descriptor instanceof ValueParameterDescriptor) {
|
||||
return InlineUtil.isInline(descriptor.getContainingDeclaration()) &&
|
||||
InlineUtil.isInlineLambdaParameter((ParameterDescriptor) descriptor);
|
||||
InlineUtil.isInlineLambdaParameter((ParameterDescriptor) descriptor) &&
|
||||
!((ValueParameterDescriptor) descriptor).isCrossinline();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user