mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[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:
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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" }
|
||||
@@ -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.*
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user