JVM_IR: do not box inline classes in suspend synthetic accessors

This commit is contained in:
pyos
2021-04-22 10:19:45 +02:00
committed by Ilmir Usmanov
parent 857bee6ced
commit 7d95943b8b
11 changed files with 90 additions and 24 deletions
@@ -10643,6 +10643,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@Test
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@Nested
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -142,16 +141,19 @@ private fun IrFunction.isStaticInlineClassReplacementDelegatingCall(): Boolean =
parentAsClass.declarations.find { it is IrAttributeContainer && it.attributeOwnerId == attributeOwnerId && it !== this }
?.isStaticInlineClassReplacement == true
internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspendOfContinuation() &&
// These are tail-call bridges and do not require any bytecode modifications.
origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER &&
origin != JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER &&
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR &&
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR &&
origin != JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE &&
origin != IrDeclarationOrigin.BRIDGE &&
origin != IrDeclarationOrigin.BRIDGE_SPECIAL &&
internal val BRIDGE_ORIGINS = setOf(
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR,
JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE,
IrDeclarationOrigin.BRIDGE,
IrDeclarationOrigin.BRIDGE_SPECIAL,
)
internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = origin !in BRIDGE_ORIGINS &&
origin != IrDeclarationOrigin.DELEGATED_MEMBER &&
!isInvokeSuspendOfContinuation() &&
!isMultifileBridge() &&
!isInvokeOfSuspendCallableReference() &&
!isBridgeToSuspendImplMethod() &&
@@ -229,20 +229,17 @@ class ExpressionCodegen(
if (irFunction.origin != JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER) {
irFunction.markLineNumber(startOffset = irFunction is IrConstructor && irFunction.isPrimary)
}
if (irFunction.isSuspend && irFunction.origin == IrDeclarationOrigin.BRIDGE) {
mv.areturn(OBJECT_TYPE)
val unboxedInlineClass =
irFunction.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
if (unboxedInlineClass != null && irFunction.origin !in BRIDGE_ORIGINS) {
result.materializeAt(unboxedInlineClass.asmType, unboxedInlineClass)
} else {
var returnType = signature.returnType
var returnIrType = if (irFunction !is IrConstructor) irFunction.returnType else context.irBuiltIns.unitType
val unboxedInlineClass =
irFunction.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
if (unboxedInlineClass != null) {
returnIrType = unboxedInlineClass
returnType = unboxedInlineClass.asmType
}
result.materializeAt(returnType, returnIrType)
mv.areturn(returnType)
val returnIrType = if (irFunction !is IrConstructor) irFunction.returnType else context.irBuiltIns.unitType
result.materializeAt(signature.returnType, returnIrType)
}
// `signature.returnType` is valid here even if the return value of a suspend function was unboxed,
// as it's still a reference type.
mv.areturn(signature.returnType)
}
val endLabel = markNewLabel()
writeLocalVariablesInTable(info, endLabel)
@@ -508,7 +505,7 @@ class ExpressionCodegen(
wrapJavaClassesIntoKClasses(mv)
MaterialValue(this, AsmTypes.K_CLASS_ARRAY_TYPE, expression.type)
}
unboxedInlineClassIrType != null && !irFunction.isInvokeSuspendOfContinuation() ->
unboxedInlineClassIrType != null && !irFunction.isInvokeSuspendOfContinuation() && irFunction.origin !in BRIDGE_ORIGINS ->
object : PromisedValue(this, unboxedInlineClassIrType.asmType, unboxedInlineClassIrType) {
override fun materializeAt(target: Type, irTarget: IrType, castForReified: Boolean) {
mv.checkcast(unboxedInlineClassIrType.asmType)
@@ -416,7 +416,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen
}.also { accessor ->
accessor.parent = parent
accessor.copyAttributes(source)
accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR)
accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, dispatchReceiverType)
accessor.returnType = source.returnType.remapTypeParameters(source, accessor)
@@ -0,0 +1,29 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
@Suppress("UNSUPPORTED_FEATURE")
inline class I(val x: Any?)
suspend fun suspendHere(): Unit = suspendCoroutineUninterceptedOrReturn { c ->
c.resume(Unit)
COROUTINE_SUSPENDED
}
class C {
private suspend fun f(): I {
suspendHere()
return I("OK")
}
fun g() = suspend { f() }
}
fun box(): String {
var result = "fail"
suspend { result = C().g()().x as String }.startCoroutine(EmptyContinuation)
return result
}
@@ -10643,6 +10643,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@Test
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@Nested
@@ -10643,6 +10643,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@Test
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@Nested
@@ -8448,6 +8448,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException")
@@ -7592,6 +7592,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException")
@@ -7003,6 +7003,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException")
@@ -7003,6 +7003,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
public void testReturnResult() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt");
}
@TestMetadata("syntheticAccessor.kt")
public void testSyntheticAccessor() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException")