[JVM_IR] Avoid unbounded recursion for recursive suspend functions.

Additionally, deal with primitive types in AddContinuationLowering.
This commit is contained in:
Mads Ager
2019-10-14 17:54:13 +02:00
committed by Ilmir Usmanov
parent ed6ca7d67e
commit 8305baa5fe
8 changed files with 24 additions and 20 deletions
@@ -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()}" }
}
@@ -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 =
@@ -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,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,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