[JVM_IR] Avoid unbounded recursion for recursive suspend functions.
Additionally, deal with primitive types in AddContinuationLowering.
This commit is contained in:
+2
-11
@@ -396,17 +396,8 @@ open class DefaultParameterInjector(
|
||||
nullConst(startOffset, endOffset, irParameter.type)
|
||||
}
|
||||
|
||||
protected open fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression = when {
|
||||
type.isFloat() -> IrConstImpl.float(startOffset, endOffset, type, 0.0F)
|
||||
type.isDouble() -> IrConstImpl.double(startOffset, endOffset, type, 0.0)
|
||||
type.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, type, false)
|
||||
type.isByte() -> IrConstImpl.byte(startOffset, endOffset, type, 0)
|
||||
type.isChar() -> IrConstImpl.char(startOffset, endOffset, type, 0.toChar())
|
||||
type.isShort() -> IrConstImpl.short(startOffset, endOffset, type, 0)
|
||||
type.isInt() -> IrConstImpl.int(startOffset, endOffset, type, 0)
|
||||
type.isLong() -> IrConstImpl.long(startOffset, endOffset, type, 0)
|
||||
else -> IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
|
||||
}
|
||||
protected open fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression =
|
||||
IrConstImpl.defaultValueForType(startOffset, endOffset, type)
|
||||
|
||||
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
||||
}
|
||||
|
||||
+4
-1
@@ -108,7 +108,7 @@ internal fun IrFunction.isInvokeSuspendOfContinuation(context: JvmBackendContext
|
||||
// the result is called 'view', just to be consistent with old backend.
|
||||
internal fun IrFunction.getOrCreateSuspendFunctionViewIfNeeded(context: JvmBackendContext): IrFunction {
|
||||
if (!isSuspend || origin == SUSPEND_FUNCTION_VIEW) return this
|
||||
return if (isSuspend) context.suspendFunctionViews.getOrPut(this) { suspendFunctionView(context) } else this
|
||||
return if (isSuspend) context.suspendFunctionViews.getOrElse(this) { suspendFunctionView(context) } else this
|
||||
}
|
||||
|
||||
private object SUSPEND_FUNCTION_VIEW : IrDeclarationOriginImpl("SUSPEND_FUNCTION_VIEW")
|
||||
@@ -143,6 +143,9 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
||||
else context.ir.symbols.continuationClass.createType(false, listOf(makeTypeProjection(returnType, Variance.INVARIANT)))
|
||||
)
|
||||
val valueParametersMapping = explicitParameters.zip(it.explicitParameters).toMap()
|
||||
// Add the suspend function view to the map before transforming the body to make sure
|
||||
// that recursive suspend functions do not lead to unbounded recursion at compile time.
|
||||
context.suspendFunctionViews.put(this, it)
|
||||
it.body = body?.deepCopyWithSymbols(this)
|
||||
it.body?.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrGetValue =
|
||||
|
||||
+5
-3
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
@@ -389,9 +390,10 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
if (irFunction.extensionReceiverParameter != null) {
|
||||
it.extensionReceiver = irNull()
|
||||
}
|
||||
for (i in irFunction.valueParameters.indices) {
|
||||
// TODO: also support primitives
|
||||
it.putValueArgument(i, irNull())
|
||||
for ((i, parameter) in irFunction.valueParameters.withIndex()) {
|
||||
val defaultValueForParameter = IrConstImpl.defaultValueForType(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.type)
|
||||
it.putValueArgument(i, defaultValueForParameter)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
class IrConstImpl<T>(
|
||||
@@ -74,5 +74,17 @@ class IrConstImpl<T>(
|
||||
|
||||
fun short(startOffset: Int, endOffset: Int, type: IrType, value: Short): IrExpression =
|
||||
IrConstImpl(startOffset, endOffset, type, IrConstKind.Short, value)
|
||||
|
||||
fun defaultValueForType(startOffset: Int, endOffset: Int, type: IrType) = when {
|
||||
type.isFloat() -> float(startOffset, endOffset, type, 0.0F)
|
||||
type.isDouble() -> double(startOffset, endOffset, type, 0.0)
|
||||
type.isBoolean() -> boolean(startOffset, endOffset, type, false)
|
||||
type.isByte() -> byte(startOffset, endOffset, type, 0)
|
||||
type.isChar() -> char(startOffset, endOffset, type, 0.toChar())
|
||||
type.isShort() -> short(startOffset, endOffset, type, 0)
|
||||
type.isInt() -> int(startOffset, endOffset, type, 0)
|
||||
type.isLong() -> long(startOffset, endOffset, type, 0)
|
||||
else -> constNull(startOffset, endOffset, type)
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
Reference in New Issue
Block a user