[JS IR] Review remarks

- Use intrinsic on this
- Enqueue invoke for DCE
- Change transform
- Ignore instead of target backend

^KT-46204 fixed
This commit is contained in:
Ilya Goncharov
2021-08-09 12:49:06 +03:00
committed by Space
parent 2f0f88062a
commit 766857881a
10 changed files with 63 additions and 57 deletions

View File

@@ -10205,6 +10205,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheck.kt");
}
@Test
@TestMetadata("suspendFunctionAsSupertypeIsCheckWithArity.kt")
public void testSuspendFunctionAsSupertypeIsCheckWithArity() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheckWithArity.kt");
}
@Test
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {

View File

@@ -22,8 +22,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
@@ -458,6 +458,12 @@ fun usefulDeclarations(
val klass = arg.getClass()
constructedClasses.addIfNotNull(klass)
}
context.intrinsics.jsInvokeSuspendSuperType,
context.intrinsics.jsInvokeSuspendSuperTypeWithReceiver,
context.intrinsics.jsInvokeSuspendSuperTypeWithReceiverAndParam -> {
invokeFunForLambda(expression)
.enqueue("intrinsic: suspendSuperType")
}
}
}

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.backend.js.export.isExported
import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.declarations.*
@@ -162,19 +163,21 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
// interface II : I
// II.prototype.foo = I.prototype.foo
if (!irClass.isInterface) {
declaration.realOverrideTarget.let {
val implClassDeclaration = it.parent as IrClass
declaration.collectRealOverrides()
.find { it.modality != Modality.ABSTRACT }
?.let {
val implClassDeclaration = it.parent as IrClass
if (implClassDeclaration.shouldCopyFrom() && !implClassDeclaration.defaultType.isFunctionType()) {
val implMethodName = context.getNameForMemberFunction(it)
val implClassName = context.getNameForClass(implClassDeclaration)
if (implClassDeclaration.shouldCopyFrom()) {
val implMethodName = context.getNameForMemberFunction(it)
val implClassName = context.getNameForClass(implClassDeclaration)
val implClassPrototype = prototypeOf(implClassName.makeRef())
val implMemberRef = JsNameRef(implMethodName, implClassPrototype)
val implClassPrototype = prototypeOf(implClassName.makeRef())
val implMemberRef = JsNameRef(implMethodName, implClassPrototype)
classModel.postDeclarationBlock.statements += jsAssignment(memberRef, implMemberRef).makeStmt()
classModel.postDeclarationBlock.statements += jsAssignment(memberRef, implMemberRef).makeStmt()
}
}
}
}
return Pair(memberRef, null)

View File

@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.backend.js.utils.getClassRef
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
@@ -232,45 +230,14 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
val suspendInvokeTransform: (IrCall, JsGenerationContext) -> JsExpression = { call, context: JsGenerationContext ->
// Because it is intrinsic, we know everything about this function
// There is callable reference as extension receiver
val invokeFun = (call.extensionReceiver as IrCall)
.getValueArgument(0)!!
.type
.getClass()!!
.declarations
.filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "invoke" }
val invokeFun = invokeFunForLambda(call)
val jsInvokeFunName = context.getNameForMemberFunction(invokeFun)
val jsExtensionReceiver = call.extensionReceiver?.accept(IrElementToJsExpressionTransformer(), context)!! as JsInvocation
val jsExtensionReceiver = call.extensionReceiver?.accept(IrElementToJsExpressionTransformer(), context)!!
val args = translateCallArguments(call, context)
val jsArgsForClosureFun = args.mapIndexed { index, _ -> JsName("${"$"}p$index") }
// Function to make closure for invoke to avoid losing this
jsExtensionReceiver.arguments[0] = JsInvocation(
JsNameRef(
Namer.BIND_FUNCTION,
JsFunction(
emptyScope,
JsBlock(
JsReturn(
JsInvocation(
JsNameRef(
jsInvokeFunName,
jsExtensionReceiver.arguments[0]
),
jsArgsForClosureFun.map { it.makeRef() }
)
)
),
"Function to make closure for invoke to avoid losing this"
).also { func ->
func.parameters.addAll(jsArgsForClosureFun.map { JsParameter(it) })
}
), JsThisRef()
)
JsInvocation(jsExtensionReceiver, args)
JsInvocation(JsNameRef(jsInvokeFunName, jsExtensionReceiver), args)
}
add(intrinsics.jsInvokeSuspendSuperType, suspendInvokeTransform)

View File

@@ -18,9 +18,8 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration
import org.jetbrains.kotlin.name.Name
@@ -118,4 +117,12 @@ fun IrBody.prependFunctionCall(
fun IrDeclaration.isImportedFromModuleOnly(): Boolean {
return isTopLevel && isEffectivelyExternal() && (getJsModule() != null && !isJsNonModule() || (parent as? IrAnnotationContainer)?.getJsModule() != null)
}
}
fun invokeFunForLambda(call: IrCall) =
call.extensionReceiver!!
.type
.getClass()!!
.declarations
.filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "invoke" }

View File

@@ -1,6 +1,6 @@
// KJS_WITH_FULL_RUNTIME
// TARGET_BACKEND: JS
// IGNORE_BACKEND: JS
// IGNORE_BACKEND: JS, JVM, JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// !LANGUAGE: +SuspendFunctionAsSupertype
import kotlin.coroutines.*

View File

@@ -10109,6 +10109,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheck.kt");
}
@Test
@TestMetadata("suspendFunctionAsSupertypeIsCheckWithArity.kt")
public void testSuspendFunctionAsSupertypeIsCheckWithArity() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheckWithArity.kt");
}
@Test
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {

View File

@@ -10205,6 +10205,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheck.kt");
}
@Test
@TestMetadata("suspendFunctionAsSupertypeIsCheckWithArity.kt")
public void testSuspendFunctionAsSupertypeIsCheckWithArity() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheckWithArity.kt");
}
@Test
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {

View File

@@ -7883,6 +7883,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheck.kt");
}
@TestMetadata("suspendFunctionAsSupertypeIsCheckWithArity.kt")
public void ignoreSuspendFunctionAsSupertypeIsCheckWithArity() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionAsSupertypeIsCheckWithArity.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}

View File

@@ -74,7 +74,7 @@ public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrRetu
): Any? {
val a = this.asDynamic()
return if (jsTypeOf(a) == "function") a(completion)
else ::invoke.invokeSuspendSuperType(completion)
else this.invokeSuspendSuperType(completion)
}
/**
@@ -97,7 +97,7 @@ public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedO
): Any? {
val a = this.asDynamic()
return if (jsTypeOf(a) == "function") a(receiver, completion)
else ::invoke.invokeSuspendSuperTypeWithReceiver(receiver, completion)
else this.invokeSuspendSuperTypeWithReceiver(receiver, completion)
}
@InlineOnly
@@ -108,7 +108,7 @@ internal actual inline fun <R, P, T> (suspend R.(P) -> T).startCoroutineUninterc
): Any? {
val a = this.asDynamic()
return if (jsTypeOf(a) == "function") a(receiver, param, completion)
else ::invoke.invokeSuspendSuperTypeWithReceiverAndParam(receiver, param, completion)
else this.invokeSuspendSuperTypeWithReceiverAndParam(receiver, param, completion)
}
/**
@@ -134,7 +134,7 @@ public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
createCoroutineFromSuspendFunction(completion) {
val a = this.asDynamic()
if (jsTypeOf(a) == "function") a(completion)
else ::invoke.invokeSuspendSuperType(completion)
else this.invokeSuspendSuperType(completion)
}
/**
@@ -161,7 +161,7 @@ public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
createCoroutineFromSuspendFunction(completion) {
val a = this.asDynamic()
if (jsTypeOf(a) == "function") a(receiver, completion)
else ::invoke.invokeSuspendSuperTypeWithReceiver(receiver, completion)
else this.invokeSuspendSuperTypeWithReceiver(receiver, completion)
}
/**