Added throwing exception if receiver type is unexpected
This assert is not generated with -opt mode
This commit is contained in:
+50
-32
@@ -894,6 +894,7 @@ internal object Devirtualization {
|
|||||||
devirtualizedCallSites: Map<IrCall, DevirtualizedCallSite>) {
|
devirtualizedCallSites: Map<IrCall, DevirtualizedCallSite>) {
|
||||||
val nativePtrType = context.builtIns.nativePtr.defaultType
|
val nativePtrType = context.builtIns.nativePtr.defaultType
|
||||||
val nativePtrEqualityOperatorSymbol = context.ir.symbols.areEqualByValue.single { it.descriptor.valueParameters[0].type == nativePtrType }
|
val nativePtrEqualityOperatorSymbol = context.ir.symbols.areEqualByValue.single { it.descriptor.valueParameters[0].type == nativePtrType }
|
||||||
|
val optimize = context.config.configuration.get(KonanConfigKeys.OPTIMIZATION) ?: false
|
||||||
|
|
||||||
irModule.transformChildrenVoid(object: IrElementTransformerVoidWithContext() {
|
irModule.transformChildrenVoid(object: IrElementTransformerVoidWithContext() {
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
@@ -934,7 +935,7 @@ internal object Devirtualization {
|
|||||||
+nullConst(expression, type)
|
+nullConst(expression, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
possibleCallees.size == 1 -> { // Monomorphic callsite.
|
optimize && possibleCallees.size == 1 -> { // Monomorphic callsite.
|
||||||
val actualCallee = possibleCallees[0].callee as DataFlowIR.FunctionSymbol.Declared
|
val actualCallee = possibleCallees[0].callee as DataFlowIR.FunctionSymbol.Declared
|
||||||
irDevirtualizedCall(expression, type, actualCallee).apply {
|
irDevirtualizedCall(expression, type, actualCallee).apply {
|
||||||
this.dispatchReceiver = dispatchReceiver
|
this.dispatchReceiver = dispatchReceiver
|
||||||
@@ -953,46 +954,63 @@ internal object Devirtualization {
|
|||||||
putValueArgument(0, irGet(receiver.symbol))
|
putValueArgument(0, irGet(receiver.symbol))
|
||||||
})
|
})
|
||||||
|
|
||||||
val branches = possibleCallees.mapIndexed { index, devirtualizedCallee ->
|
val branches = mutableListOf<IrBranchImpl>()
|
||||||
|
possibleCallees.mapIndexedTo(branches) { index, devirtualizedCallee ->
|
||||||
val actualCallee = devirtualizedCallee.callee as DataFlowIR.FunctionSymbol.Declared
|
val actualCallee = devirtualizedCallee.callee as DataFlowIR.FunctionSymbol.Declared
|
||||||
val actualReceiverType = devirtualizedCallee.receiverType as DataFlowIR.Type.Declared
|
val actualReceiverType = devirtualizedCallee.receiverType as DataFlowIR.Type.Declared
|
||||||
val expectedTypeInfo = IrPrivateClassReferenceImpl(
|
val expectedTypeInfo = IrPrivateClassReferenceImpl(
|
||||||
startOffset,
|
startOffset = startOffset,
|
||||||
endOffset,
|
endOffset = endOffset,
|
||||||
nativePtrType,
|
type = nativePtrType,
|
||||||
IrClassSymbolImpl(dispatchReceiver.type.getErasedTypeClass()),
|
symbol = IrClassSymbolImpl(dispatchReceiver.type.getErasedTypeClass()),
|
||||||
receiver.type,
|
classType = receiver.type,
|
||||||
actualReceiverType.module!!.descriptor,
|
moduleDescriptor = actualReceiverType.module!!.descriptor,
|
||||||
actualReceiverType.module.numberOfClasses,
|
totalClasses = actualReceiverType.module.numberOfClasses,
|
||||||
actualReceiverType.symbolTableIndex)
|
classIndex = actualReceiverType.symbolTableIndex)
|
||||||
val condition =
|
val condition =
|
||||||
if (index == possibleCallees.size - 1)
|
if (optimize && index == possibleCallees.size - 1)
|
||||||
irTrue()
|
irTrue() // Don't check last type in optimize mode.
|
||||||
else
|
else
|
||||||
irCall(nativePtrEqualityOperatorSymbol).apply {
|
irCall(nativePtrEqualityOperatorSymbol).apply {
|
||||||
putValueArgument(0, irGet(typeInfo.symbol))
|
putValueArgument(0, irGet(typeInfo.symbol))
|
||||||
putValueArgument(1, expectedTypeInfo)
|
putValueArgument(1, expectedTypeInfo)
|
||||||
}
|
}
|
||||||
IrBranchImpl(
|
IrBranchImpl(
|
||||||
startOffset,
|
startOffset = startOffset,
|
||||||
endOffset,
|
endOffset = endOffset,
|
||||||
condition,
|
condition = condition,
|
||||||
irDevirtualizedCall(expression, type, actualCallee).apply {
|
result = irDevirtualizedCall(expression, type, actualCallee).apply {
|
||||||
this.dispatchReceiver = irGet(receiver.symbol)
|
this.dispatchReceiver = irGet(receiver.symbol)
|
||||||
this.extensionReceiver = extensionReceiver?.let { irGet(it.symbol) }
|
this.extensionReceiver = extensionReceiver?.let { irGet(it.symbol) }
|
||||||
expression.descriptor.valueParameters.forEach {
|
expression.descriptor.valueParameters.forEach {
|
||||||
this.putValueArgument(it.index, irGet(parameters[it]!!.symbol))
|
putValueArgument(it.index, irGet(parameters[it]!!.symbol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (!optimize) { // Add else branch throwing exception for debug purposes.
|
||||||
|
branches.add(IrBranchImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
condition = irTrue(),
|
||||||
|
result = irCall(context.ir.symbols.throwInvalidReceiverTypeException).apply {
|
||||||
|
putValueArgument(0,
|
||||||
|
irCall(context.ir.symbols.kClassImplConstructor,
|
||||||
|
listOf(dispatchReceiver.type)
|
||||||
|
).apply {
|
||||||
|
putValueArgument(0, irGet(typeInfo.symbol))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
+IrWhenImpl(
|
+IrWhenImpl(
|
||||||
startOffset,
|
startOffset = startOffset,
|
||||||
endOffset,
|
endOffset = endOffset,
|
||||||
type,
|
type = type,
|
||||||
expression.origin,
|
origin = expression.origin,
|
||||||
branches
|
branches = branches
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1002,15 +1020,15 @@ internal object Devirtualization {
|
|||||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType,
|
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType,
|
||||||
devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) =
|
devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) =
|
||||||
IrPrivateFunctionCallImpl(
|
IrPrivateFunctionCallImpl(
|
||||||
startOffset,
|
startOffset = startOffset,
|
||||||
endOffset,
|
endOffset = endOffset,
|
||||||
actualType,
|
type = actualType,
|
||||||
callee.symbol,
|
symbol = callee.symbol,
|
||||||
callee.descriptor,
|
descriptor = callee.descriptor,
|
||||||
(callee as? IrCallImpl)?.typeArguments,
|
typeArguments = (callee as? IrCallImpl)?.typeArguments,
|
||||||
devirtualizedCallee.module.descriptor,
|
moduleDescriptor = devirtualizedCallee.module.descriptor,
|
||||||
devirtualizedCallee.module.numberOfFunctions,
|
totalFunctions = devirtualizedCallee.module.numberOfFunctions,
|
||||||
devirtualizedCallee.symbolTableIndex
|
functionIndex = devirtualizedCallee.symbolTableIndex
|
||||||
)
|
)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user