Turned on bridges inlining
This commit is contained in:
+38
-17
@@ -127,7 +127,12 @@ class IrFileImpl(entry: SourceManager.FileEntry) : IrFile {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
internal interface IrPrivateFunctionCall : IrCall {
|
internal interface IrPrivateFunctionCall : IrExpression {
|
||||||
|
val valueArgumentsCount: Int
|
||||||
|
fun getValueArgument(index: Int): IrExpression?
|
||||||
|
fun putValueArgument(index: Int, valueArgument: IrExpression?)
|
||||||
|
fun removeValueArgument(index: Int)
|
||||||
|
|
||||||
val virtualCallee: IrCall?
|
val virtualCallee: IrCall?
|
||||||
val dfgSymbol: DataFlowIR.FunctionSymbol.Declared
|
val dfgSymbol: DataFlowIR.FunctionSymbol.Declared
|
||||||
val moduleDescriptor: ModuleDescriptor
|
val moduleDescriptor: ModuleDescriptor
|
||||||
@@ -138,31 +143,47 @@ internal interface IrPrivateFunctionCall : IrCall {
|
|||||||
internal class IrPrivateFunctionCallImpl(startOffset: Int,
|
internal class IrPrivateFunctionCallImpl(startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
type: IrType,
|
type: IrType,
|
||||||
override val symbol: IrFunctionSymbol,
|
override val valueArgumentsCount: Int,
|
||||||
override val descriptor: FunctionDescriptor,
|
|
||||||
override val virtualCallee: IrCall?,
|
override val virtualCallee: IrCall?,
|
||||||
typeArgumentsCount: Int,
|
|
||||||
override val dfgSymbol: DataFlowIR.FunctionSymbol.Declared,
|
override val dfgSymbol: DataFlowIR.FunctionSymbol.Declared,
|
||||||
override val moduleDescriptor: ModuleDescriptor,
|
override val moduleDescriptor: ModuleDescriptor,
|
||||||
override val totalFunctions: Int,
|
override val totalFunctions: Int,
|
||||||
override val functionIndex: Int
|
override val functionIndex: Int
|
||||||
) : IrPrivateFunctionCall, IrCallWithIndexedArgumentsBase(
|
) : IrPrivateFunctionCall, IrExpressionBase(startOffset, endOffset, type) {
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
type,
|
|
||||||
typeArgumentsCount = typeArgumentsCount,
|
|
||||||
valueArgumentsCount = symbol.descriptor.valueParameters.size
|
|
||||||
) {
|
|
||||||
|
|
||||||
override val superQualifierSymbol: IrClassSymbol?
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||||
get() = null
|
return visitor.visitExpression(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
override val superQualifier: ClassDescriptor?
|
private val argumentsByParameterIndex: Array<IrExpression?> = arrayOfNulls(valueArgumentsCount)
|
||||||
get() = null
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun getValueArgument(index: Int): IrExpression? {
|
||||||
visitor.visitCall(this, data)
|
if (index >= valueArgumentsCount) {
|
||||||
|
throw AssertionError("$this: No such value argument slot: $index")
|
||||||
|
}
|
||||||
|
return argumentsByParameterIndex[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putValueArgument(index: Int, valueArgument: IrExpression?) {
|
||||||
|
if (index >= valueArgumentsCount) {
|
||||||
|
throw AssertionError("$this: No such value argument slot: $index")
|
||||||
|
}
|
||||||
|
argumentsByParameterIndex[index] = valueArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeValueArgument(index: Int) {
|
||||||
|
argumentsByParameterIndex[index] = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||||
|
argumentsByParameterIndex.forEach { it?.accept(visitor, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||||
|
argumentsByParameterIndex.forEachIndexed { i, irExpression ->
|
||||||
|
argumentsByParameterIndex[i] = irExpression?.transform(transformer, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IrPrivateClassReference : IrClassReference {
|
internal interface IrPrivateClassReference : IrClassReference {
|
||||||
|
|||||||
+2
-2
@@ -258,8 +258,8 @@ internal fun RuntimeAware.getLlvmFunctionType(function: FunctionDescriptor): LLV
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun RuntimeAware.getLlvmFunctionType(symbol: DataFlowIR.FunctionSymbol): LLVMTypeRef {
|
internal fun RuntimeAware.getLlvmFunctionType(symbol: DataFlowIR.FunctionSymbol): LLVMTypeRef {
|
||||||
val returnType = if (symbol.returnsUnit) voidType else getLLVMType(symbol.returnType)
|
val returnType = if (symbol.returnsUnit) voidType else getLLVMType(symbol.returnParameter.type)
|
||||||
val paramTypes = ArrayList(symbol.parameterTypes.map { getLLVMType(it) })
|
val paramTypes = ArrayList(symbol.parameters.map { getLLVMType(it.type) })
|
||||||
if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr)
|
if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr)
|
||||||
|
|
||||||
return functionType(returnType, isVarArg = false, paramTypes = *paramTypes.toTypedArray())
|
return functionType(returnType, isVarArg = false, paramTypes = *paramTypes.toTypedArray())
|
||||||
|
|||||||
+29
-5
@@ -845,6 +845,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
is IrSuspendableExpression ->
|
is IrSuspendableExpression ->
|
||||||
return evaluateSuspendableExpression (value)
|
return evaluateSuspendableExpression (value)
|
||||||
is IrSuspensionPoint -> return evaluateSuspensionPoint (value)
|
is IrSuspensionPoint -> return evaluateSuspensionPoint (value)
|
||||||
|
is IrPrivateFunctionCall -> return evaluatePrivateFunctionCall (value)
|
||||||
is IrPrivateClassReference ->
|
is IrPrivateClassReference ->
|
||||||
return evaluatePrivateClassReference (value)
|
return evaluatePrivateClassReference (value)
|
||||||
else -> {
|
else -> {
|
||||||
@@ -2092,9 +2093,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callee is IrPrivateFunctionCall)
|
|
||||||
return evaluatePrivateFunctionCall(callee, argsWithContinuationIfNeeded, callee.virtualCallee?.let { resultLifetime(it) } ?: resultLifetime)
|
|
||||||
|
|
||||||
when {
|
when {
|
||||||
descriptor.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
descriptor.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||||
return evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
return evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
||||||
@@ -2108,7 +2106,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun evaluatePrivateFunctionCall(callee: IrPrivateFunctionCall, args: List<LLVMValueRef>, resultLifetime: Lifetime): LLVMValueRef {
|
private fun evaluatePrivateFunctionCall(callee: IrPrivateFunctionCall): LLVMValueRef {
|
||||||
|
val args = (0 until callee.valueArgumentsCount).map { index ->
|
||||||
|
callee.getValueArgument(index)?.let { evaluateExpression(it) }
|
||||||
|
?: run {
|
||||||
|
assert(index == callee.valueArgumentsCount - 1) { "Only last argument may be null - for suspend functions" }
|
||||||
|
getContinuation()
|
||||||
|
}
|
||||||
|
}
|
||||||
val dfgSymbol = callee.dfgSymbol
|
val dfgSymbol = callee.dfgSymbol
|
||||||
val functionIndex = callee.functionIndex
|
val functionIndex = callee.functionIndex
|
||||||
val function = if (callee.moduleDescriptor == context.irModule!!.descriptor) {
|
val function = if (callee.moduleDescriptor == context.irModule!!.descriptor) {
|
||||||
@@ -2121,7 +2126,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return call(callee.symbol.owner, function, args, resultLifetime)
|
return call(dfgSymbol, function, args, resultLifetime = Lifetime.GLOBAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -2567,6 +2572,25 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: it seems to be much more reliable to get args as a mapping from parameter descriptor to LLVM value,
|
||||||
|
// instead of a plain list.
|
||||||
|
// In such case it would be possible to check that all args are available and in the correct order.
|
||||||
|
// However, it currently requires some refactoring to be performed.
|
||||||
|
private fun call(symbol: DataFlowIR.FunctionSymbol, function: LLVMValueRef, args: List<LLVMValueRef>,
|
||||||
|
resultLifetime: Lifetime): LLVMValueRef {
|
||||||
|
val result = call(function, args, resultLifetime)
|
||||||
|
if (symbol.returnsNothing) {
|
||||||
|
functionGenerationContext.unreachable()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LLVMGetReturnType(getFunctionType(function)) == voidType) {
|
||||||
|
return codegen.theUnitInstanceRef.llvm
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
private fun call(function: LLVMValueRef, args: List<LLVMValueRef>,
|
private fun call(function: LLVMValueRef, args: List<LLVMValueRef>,
|
||||||
resultLifetime: Lifetime = Lifetime.IRRELEVANT): LLVMValueRef {
|
resultLifetime: Lifetime = Lifetime.IRRELEVANT): LLVMValueRef {
|
||||||
return functionGenerationContext.call(function, args, resultLifetime, currentCodeContext.exceptionHandler)
|
return functionGenerationContext.call(function, args, resultLifetime, currentCodeContext.exceptionHandler)
|
||||||
|
|||||||
+31
-10
@@ -300,13 +300,26 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FunctionSymbolBase(val parameterTypes: IntArray, val returnType: Int, val attributes: Int, val escapes: Int?, val pointsTo: IntArray?) {
|
class FunctionParameter(val type: Int, val boxFunction: Int?, val unboxFunction: Int?) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readIntArray(), data.readInt(), data.readInt(), data.readNullableInt(), data.readNullable { readIntArray() })
|
constructor(data: ArraySlice) : this(data.readInt(), data.readNullableInt(), data.readNullableInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeIntArray(parameterTypes)
|
result.writeInt(type)
|
||||||
result.writeInt(returnType)
|
result.writeNullableInt(boxFunction)
|
||||||
|
result.writeNullableInt(unboxFunction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FunctionSymbolBase(val parameters: Array<FunctionParameter>, val returnParameter: FunctionParameter,
|
||||||
|
val attributes: Int, val escapes: Int?, val pointsTo: IntArray?) {
|
||||||
|
|
||||||
|
constructor(data: ArraySlice) : this(data.readArray { FunctionParameter(data) }, FunctionParameter(data), data.readInt(),
|
||||||
|
data.readNullableInt(), data.readNullable { readIntArray() })
|
||||||
|
|
||||||
|
fun write(result: ArraySlice) {
|
||||||
|
result.writeArray(parameters) { it.write(this) }
|
||||||
|
returnParameter.write(result)
|
||||||
result.writeInt(attributes)
|
result.writeInt(attributes)
|
||||||
result.writeNullableInt(escapes)
|
result.writeNullableInt(escapes)
|
||||||
result.writeNullable(pointsTo) { writeIntArray(it) }
|
result.writeNullable(pointsTo) { writeIntArray(it) }
|
||||||
@@ -814,10 +827,14 @@ internal object DFGSerializer {
|
|||||||
.sortedBy { it.value }
|
.sortedBy { it.value }
|
||||||
.map {
|
.map {
|
||||||
|
|
||||||
|
fun buildFunctionParameter(parameter: DataFlowIR.FunctionParameter) =
|
||||||
|
FunctionParameter(typeMap[parameter.type]!!, parameter.boxFunction?.let { functionSymbolMap[it]!! },
|
||||||
|
parameter.unboxFunction?.let { functionSymbolMap[it]!! })
|
||||||
|
|
||||||
fun buildFunctionSymbolBase(symbol: DataFlowIR.FunctionSymbol) =
|
fun buildFunctionSymbolBase(symbol: DataFlowIR.FunctionSymbol) =
|
||||||
FunctionSymbolBase(
|
FunctionSymbolBase(
|
||||||
symbol.parameterTypes.map { typeMap[it]!! }.toIntArray(),
|
symbol.parameters.map { buildFunctionParameter(it) }.toTypedArray(),
|
||||||
typeMap[symbol.returnType]!!,
|
buildFunctionParameter(symbol.returnParameter),
|
||||||
symbol.attributes,
|
symbol.attributes,
|
||||||
symbol.escapes,
|
symbol.escapes,
|
||||||
symbol.pointsTo
|
symbol.pointsTo
|
||||||
@@ -1016,8 +1033,6 @@ internal object DFGSerializer {
|
|||||||
module, symbolTableIndex, attributes, null, private.name)
|
module, symbolTableIndex, attributes, null, private.name)
|
||||||
}
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
parameterTypes = it.base.parameterTypes.map { types[it] }.toTypedArray()
|
|
||||||
returnType = types[it.base.returnType]
|
|
||||||
escapes = it.base.escapes
|
escapes = it.base.escapes
|
||||||
pointsTo = it.base.pointsTo
|
pointsTo = it.base.pointsTo
|
||||||
}
|
}
|
||||||
@@ -1043,9 +1058,15 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun buildFunctionParameter(parameter: FunctionParameter) =
|
||||||
|
DataFlowIR.FunctionParameter(types[parameter.type], parameter.boxFunction?.let { functionSymbols[it] },
|
||||||
|
parameter.unboxFunction?.let { functionSymbols[it] })
|
||||||
|
|
||||||
symbolTable.functionSymbols.forEachIndexed { index, symbol ->
|
symbolTable.functionSymbols.forEachIndexed { index, symbol ->
|
||||||
val deserializedSymbol = functionSymbols[index] as? DataFlowIR.FunctionSymbol.Declared
|
val deserializedSymbol = functionSymbols[index]
|
||||||
?: return@forEachIndexed
|
deserializedSymbol.parameters = symbol.base.parameters.map { buildFunctionParameter(it) }.toTypedArray()
|
||||||
|
deserializedSymbol.returnParameter = buildFunctionParameter(symbol.base.returnParameter)
|
||||||
|
deserializedSymbol as? DataFlowIR.FunctionSymbol.Declared ?: return@forEachIndexed
|
||||||
val bridgeTarget = if (deserializedSymbol is DataFlowIR.FunctionSymbol.Public)
|
val bridgeTarget = if (deserializedSymbol is DataFlowIR.FunctionSymbol.Public)
|
||||||
symbol.public!!.bridgeTarget
|
symbol.public!!.bridgeTarget
|
||||||
else
|
else
|
||||||
|
|||||||
+23
-12
@@ -121,9 +121,11 @@ internal object DataFlowIR {
|
|||||||
val RETURNS_NOTHING = 4
|
val RETURNS_NOTHING = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FunctionParameter(val type: Type, val boxFunction: FunctionSymbol?, val unboxFunction: FunctionSymbol?)
|
||||||
|
|
||||||
abstract class FunctionSymbol(val attributes: Int, val name: String?) {
|
abstract class FunctionSymbol(val attributes: Int, val name: String?) {
|
||||||
lateinit var parameterTypes: Array<Type>
|
lateinit var parameters: Array<FunctionParameter>
|
||||||
lateinit var returnType: Type
|
lateinit var returnParameter: FunctionParameter
|
||||||
|
|
||||||
val isGlobalInitializer = attributes.and(FunctionAttributes.IS_GLOBAL_INITIALIZER) != 0
|
val isGlobalInitializer = attributes.and(FunctionAttributes.IS_GLOBAL_INITIALIZER) != 0
|
||||||
val returnsUnit = attributes.and(FunctionAttributes.RETURNS_UNIT) != 0
|
val returnsUnit = attributes.and(FunctionAttributes.RETURNS_UNIT) != 0
|
||||||
@@ -266,7 +268,7 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
fun debugOutput() {
|
fun debugOutput() {
|
||||||
println("FUNCTION $symbol")
|
println("FUNCTION $symbol")
|
||||||
println("Params: ${symbol.parameterTypes.contentToString()}")
|
println("Params: ${symbol.parameters.contentToString()}")
|
||||||
val ids = body.nodes.withIndex().associateBy({ it.value }, { it.index })
|
val ids = body.nodes.withIndex().associateBy({ it.value }, { it.index })
|
||||||
body.nodes.forEach {
|
body.nodes.forEach {
|
||||||
println(" NODE #${ids[it]!!}")
|
println(" NODE #${ids[it]!!}")
|
||||||
@@ -555,6 +557,12 @@ internal object DataFlowIR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mapTypeToFunctionParameter(type: IrType) =
|
||||||
|
type.getInlinedClass().let { inlinedClass ->
|
||||||
|
FunctionParameter(mapType(type), inlinedClass?.let { mapFunction(context.getBoxFunction(it)) },
|
||||||
|
inlinedClass?.let { mapFunction(context.getUnboxFunction(it)) })
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: use from LlvmDeclarations.
|
// TODO: use from LlvmDeclarations.
|
||||||
private fun getFqName(descriptor: DeclarationDescriptor): FqName =
|
private fun getFqName(descriptor: DeclarationDescriptor): FqName =
|
||||||
descriptor.parent.fqNameSafe.child(descriptor.name)
|
descriptor.parent.fqNameSafe.child(descriptor.name)
|
||||||
@@ -602,7 +610,7 @@ internal object DataFlowIR {
|
|||||||
val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget)
|
val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget)
|
||||||
val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null
|
val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null
|
||||||
&& !classDescriptor.isNonGeneratedAnnotation()
|
&& !classDescriptor.isNonGeneratedAnnotation()
|
||||||
&& (it.isOverridableOrOverrides || bridgeTarget != null || descriptor.name.asString().contains("<bridge-") || !classDescriptor.isFinal())
|
&& (it.isOverridableOrOverrides || bridgeTarget != null || descriptor.isSpecial || !classDescriptor.isFinal())
|
||||||
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
|
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
|
||||||
if (it.isExported())
|
if (it.isExported())
|
||||||
FunctionSymbol.Public(name.localHash.value, module, symbolTableIndex, attributes, bridgeTargetSymbol, takeName { name })
|
FunctionSymbol.Public(name.localHash.value, module, symbolTableIndex, attributes, bridgeTargetSymbol, takeName { name })
|
||||||
@@ -612,18 +620,21 @@ internal object DataFlowIR {
|
|||||||
}
|
}
|
||||||
functionMap[it] = symbol
|
functionMap[it] = symbol
|
||||||
|
|
||||||
symbol.parameterTypes =
|
symbol.parameters =
|
||||||
(descriptor.allParameters.map { it.type } + (if (descriptor.isSuspend) listOf(continuationType) else emptyList()))
|
(descriptor.allParameters.map { it.type } + (if (descriptor.isSuspend) listOf(continuationType) else emptyList()))
|
||||||
.map { mapType(it) }
|
.map { mapTypeToFunctionParameter(it) }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
symbol.returnType = mapType(if (descriptor.isSuspend)
|
symbol.returnParameter = mapTypeToFunctionParameter(if (descriptor.isSuspend)
|
||||||
context.irBuiltIns.anyType
|
context.irBuiltIns.anyType
|
||||||
else
|
else
|
||||||
descriptor.returnType)
|
descriptor.returnType)
|
||||||
|
|
||||||
return symbol
|
return symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val FunctionDescriptor.isSpecial get() =
|
||||||
|
name.asString().let { it.contains("<bridge-") || it.contains("<box>") || it.contains("<unbox>") }
|
||||||
|
|
||||||
private fun mapPropertyInitializer(descriptor: IrField): FunctionSymbol = descriptor.original.let {
|
private fun mapPropertyInitializer(descriptor: IrField): FunctionSymbol = descriptor.original.let {
|
||||||
functionMap[it]?.let { return it }
|
functionMap[it]?.let { return it }
|
||||||
|
|
||||||
@@ -633,8 +644,8 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
functionMap[it] = symbol
|
functionMap[it] = symbol
|
||||||
|
|
||||||
symbol.parameterTypes = emptyArray()
|
symbol.parameters = emptyArray()
|
||||||
symbol.returnType = mapClassReferenceType(context.ir.symbols.unit.owner)
|
symbol.returnParameter = mapTypeToFunctionParameter(context.irBuiltIns.unitType)
|
||||||
return symbol
|
return symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+80
-99
@@ -27,9 +27,6 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.getValueArgument
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrWhenImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrWhenImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
@@ -236,8 +233,8 @@ internal object Devirtualization {
|
|||||||
// Rapid Type Analysis: find all instantiations and conservatively estimate call graph.
|
// Rapid Type Analysis: find all instantiations and conservatively estimate call graph.
|
||||||
// Add all final parameters of the roots.
|
// Add all final parameters of the roots.
|
||||||
rootSet.forEach {
|
rootSet.forEach {
|
||||||
it.parameterTypes
|
it.parameters
|
||||||
.map { it.resolved() }
|
.map { it.type.resolved() }
|
||||||
.filter { it.isFinal }
|
.filter { it.isFinal }
|
||||||
.forEach { addInstantiatingClass(it) }
|
.forEach { addInstantiatingClass(it) }
|
||||||
}
|
}
|
||||||
@@ -323,7 +320,7 @@ internal object Devirtualization {
|
|||||||
|
|
||||||
DEBUG_OUTPUT(1) { println("Function $resolvedFunctionSymbol is external") }
|
DEBUG_OUTPUT(1) { println("Function $resolvedFunctionSymbol is external") }
|
||||||
|
|
||||||
val resolvedReturnType = symbol.returnType.resolved()
|
val resolvedReturnType = symbol.returnParameter.type.resolved()
|
||||||
if (resolvedReturnType.isFinal) {
|
if (resolvedReturnType.isFinal) {
|
||||||
|
|
||||||
DEBUG_OUTPUT(1) { println("Adding return type as it is final") }
|
DEBUG_OUTPUT(1) { println("Adding return type as it is final") }
|
||||||
@@ -373,7 +370,7 @@ internal object Devirtualization {
|
|||||||
if (node.receiverType == DataFlowIR.Type.Virtual)
|
if (node.receiverType == DataFlowIR.Type.Virtual)
|
||||||
continue@nodeLoop
|
continue@nodeLoop
|
||||||
val receiverType = node.receiverType.resolved()
|
val receiverType = node.receiverType.resolved()
|
||||||
val vCallReturnType = node.callee.returnType.resolved()
|
val vCallReturnType = node.callee.returnParameter.type.resolved()
|
||||||
|
|
||||||
DEBUG_OUTPUT(1) {
|
DEBUG_OUTPUT(1) {
|
||||||
println("Adding virtual callsite:")
|
println("Adding virtual callsite:")
|
||||||
@@ -737,11 +734,11 @@ internal object Devirtualization {
|
|||||||
if (symbol is DataFlowIR.FunctionSymbol.External) return null
|
if (symbol is DataFlowIR.FunctionSymbol.External) return null
|
||||||
constraintGraph.functions[symbol]?.let { return it }
|
constraintGraph.functions[symbol]?.let { return it }
|
||||||
|
|
||||||
val parameters = Array(symbol.parameterTypes.size) { ordinaryNode { "Param#$it\$$symbol" } }
|
val parameters = Array(symbol.parameters.size) { ordinaryNode { "Param#$it\$$symbol" } }
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
// Exported function from the current module.
|
// Exported function from the current module.
|
||||||
symbol.parameterTypes.forEachIndexed { index, type ->
|
symbol.parameters.forEachIndexed { index, type ->
|
||||||
val resolvedType = type.resolved()
|
val resolvedType = type.type.resolved()
|
||||||
val node = if (!resolvedType.isFinal)
|
val node = if (!resolvedType.isFinal)
|
||||||
constraintGraph.virtualNode
|
constraintGraph.virtualNode
|
||||||
else
|
else
|
||||||
@@ -858,7 +855,7 @@ internal object Devirtualization {
|
|||||||
function.parameters[node.index]
|
function.parameters[node.index]
|
||||||
|
|
||||||
is DataFlowIR.Node.StaticCall ->
|
is DataFlowIR.Node.StaticCall ->
|
||||||
doCall(node.callee, node.arguments, node.callee.returnType.resolved(), node.receiverType?.resolved())
|
doCall(node.callee, node.arguments, node.callee.returnParameter.type.resolved(), node.receiverType?.resolved())
|
||||||
|
|
||||||
is DataFlowIR.Node.NewObject -> {
|
is DataFlowIR.Node.NewObject -> {
|
||||||
val returnType = node.constructedType.resolved()
|
val returnType = node.constructedType.resolved()
|
||||||
@@ -901,7 +898,7 @@ internal object Devirtualization {
|
|||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
|
|
||||||
val returnType = node.callee.returnType.resolved()
|
val returnType = node.callee.returnParameter.type.resolved()
|
||||||
val receiverNode = edgeToConstraintNode(node.arguments[0])
|
val receiverNode = edgeToConstraintNode(node.arguments[0])
|
||||||
if (receiverType == DataFlowIR.Type.Virtual)
|
if (receiverType == DataFlowIR.Type.Virtual)
|
||||||
constraintGraph.virtualNode.addEdge(receiverNode)
|
constraintGraph.virtualNode.addEdge(receiverNode)
|
||||||
@@ -1001,13 +998,8 @@ internal object Devirtualization {
|
|||||||
private fun devirtualize(irModule: IrModuleFragment, context: Context,
|
private fun devirtualize(irModule: IrModuleFragment, context: Context,
|
||||||
moduleDFG: ModuleDFG, externalModulesDFG: ExternalModulesDFG,
|
moduleDFG: ModuleDFG, externalModulesDFG: ExternalModulesDFG,
|
||||||
devirtualizedCallSites: Map<IrCall, DevirtualizedCallSite>) {
|
devirtualizedCallSites: Map<IrCall, DevirtualizedCallSite>) {
|
||||||
val nativePtrType = context.ir.symbols.nativePtrType
|
|
||||||
val nativePtrEqualityOperatorSymbol = context.ir.symbols.areEqualByValue[PrimitiveBinaryType.POINTER]!!
|
val nativePtrEqualityOperatorSymbol = context.ir.symbols.areEqualByValue[PrimitiveBinaryType.POINTER]!!
|
||||||
val optimize = context.shouldOptimize()
|
val optimize = context.shouldOptimize()
|
||||||
/*
|
|
||||||
val boxFunctions = ValueType.values().associate { context.ir.symbols.boxFunctions[it]!! to it }
|
|
||||||
val unboxFunctions = ValueType.values().associate { context.ir.symbols.getUnboxFunction(it) to it }
|
|
||||||
*/
|
|
||||||
|
|
||||||
fun DataFlowIR.Type.resolved(): DataFlowIR.Type.Declared {
|
fun DataFlowIR.Type.resolved(): DataFlowIR.Type.Declared {
|
||||||
if (this is DataFlowIR.Type.Declared) return this
|
if (this is DataFlowIR.Type.Declared) return this
|
||||||
@@ -1021,11 +1013,8 @@ internal object Devirtualization {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// TODO: do it more reliably.
|
||||||
fun IrExpression.isBoxOrUnboxCall() = this is IrCall && (boxFunctions[symbol] != null || unboxFunctions[symbol] != null)
|
fun IrExpression.isBoxOrUnboxCall() = this is IrCall && symbol.owner.name.asString().let { it.contains("<box>") || it.contains("<unbox>") }
|
||||||
*/
|
|
||||||
|
|
||||||
fun IrExpression.isBoxOrUnboxCall() = false
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irCoerce(value: IrExpression, coercion: IrFunctionSymbol?) =
|
fun IrBuilderWithScope.irCoerce(value: IrExpression, coercion: IrFunctionSymbol?) =
|
||||||
if (coercion == null)
|
if (coercion == null)
|
||||||
@@ -1034,6 +1023,23 @@ internal object Devirtualization {
|
|||||||
addArguments(listOf(coercion.descriptor.explicitParameters.single() to value))
|
addArguments(listOf(coercion.descriptor.explicitParameters.single() to value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.irCoerce(value: IrExpression, coercion: DataFlowIR.FunctionSymbol.Declared?) =
|
||||||
|
if (coercion == null)
|
||||||
|
value
|
||||||
|
else IrPrivateFunctionCallImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
type = value.type, // TODO: What type is actually must be here?
|
||||||
|
valueArgumentsCount = 1,
|
||||||
|
virtualCallee = null,
|
||||||
|
dfgSymbol = coercion,
|
||||||
|
moduleDescriptor = coercion.module.descriptor,
|
||||||
|
totalFunctions = coercion.module.numberOfFunctions,
|
||||||
|
functionIndex = coercion.symbolTableIndex
|
||||||
|
).apply {
|
||||||
|
putValueArgument(0, value)
|
||||||
|
}
|
||||||
|
|
||||||
class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) {
|
class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) {
|
||||||
fun getFullValue(irBuilder: IrBuilderWithScope) = irBuilder.run {
|
fun getFullValue(irBuilder: IrBuilderWithScope) = irBuilder.run {
|
||||||
irCoerce(irGet(value), coercion)
|
irCoerce(irGet(value), coercion)
|
||||||
@@ -1065,89 +1071,74 @@ internal object Devirtualization {
|
|||||||
, coercion.symbol)
|
, coercion.symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
class CoercionPair(val coerceFunction: DataFlowIR.FunctionSymbol.Declared, val uncoerceFunction: DataFlowIR.FunctionSymbol.Declared)
|
||||||
fun assertCoercionsMatch(coercion1: IrFunctionSymbol, coercion2: IrFunctionSymbol) {
|
|
||||||
boxFunctions[coercion1]?.let { assert (unboxFunctions[coercion2] == it)
|
fun getTypeConversion(actualType: DataFlowIR.FunctionParameter, targetType: DataFlowIR.FunctionParameter): CoercionPair? {
|
||||||
{ "Incosistent coercions: ${coercion1.descriptor}, ${coercion2.descriptor}" }
|
if (actualType.boxFunction == null && targetType.boxFunction == null) return null
|
||||||
}
|
if (actualType.boxFunction != null && targetType.boxFunction != null) {
|
||||||
unboxFunctions[coercion1]?.let { assert (boxFunctions[coercion2] == it)
|
assert (actualType.type.resolved() == targetType.type.resolved())
|
||||||
{ "Incosistent coercions: ${coercion1.descriptor}, ${coercion2.descriptor}" }
|
{ "Inconsistent types: ${actualType.type} and ${targetType.type}" }
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
if (actualType.boxFunction == null)
|
||||||
|
return CoercionPair(targetType.unboxFunction!!.resolved() as DataFlowIR.FunctionSymbol.Declared,
|
||||||
|
targetType.boxFunction!!.resolved() as DataFlowIR.FunctionSymbol.Declared)
|
||||||
|
return CoercionPair(actualType.boxFunction!!.resolved() as DataFlowIR.FunctionSymbol.Declared,
|
||||||
|
actualType.unboxFunction!!.resolved() as DataFlowIR.FunctionSymbol.Declared)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.irCoerceIfNeeded(type: DataFlowIR.Type.Declared, targetType: DataFlowIR.Type.Declared,
|
fun IrBuilderWithScope.irCoerceIfNeeded(type: DataFlowIR.FunctionParameter, targetType: DataFlowIR.FunctionParameter,
|
||||||
possiblyCoercedValue: PossiblyCoercedValue): IrExpression {
|
possiblyCoercedValue: PossiblyCoercedValue): IrExpression {
|
||||||
val value = possiblyCoercedValue.value
|
val value = possiblyCoercedValue.value
|
||||||
val prevCoercion = possiblyCoercedValue.coercion
|
val prevCoercion = possiblyCoercedValue.coercion
|
||||||
|
|
||||||
val coercion = context.ir.symbols.getTypeConversion(type.correspondingValueType, targetType.correspondingValueType)
|
val coercion = getTypeConversion(type, targetType)
|
||||||
?: return possiblyCoercedValue.getFullValue(this)
|
?: return possiblyCoercedValue.getFullValue(this)
|
||||||
if (prevCoercion == null)
|
if (prevCoercion == null)
|
||||||
return irCoerce(irGet(value), coercion)
|
return irCoerce(irGet(value), coercion.coerceFunction)
|
||||||
assertCoercionsMatch(coercion, prevCoercion)
|
val expectedUncoercion = coercion.uncoerceFunction
|
||||||
|
val actualUncoercion = moduleDFG.symbolTable.mapFunction(prevCoercion.owner).resolved()
|
||||||
|
assert(actualUncoercion == expectedUncoercion) { "Incosistent coercions: ${expectedUncoercion}, ${actualUncoercion}" }
|
||||||
return irGet(value)
|
return irGet(value)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
fun irDevirtualizedCall(callee: IrCall, actualType: IrType, devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) =
|
||||||
devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) =
|
|
||||||
IrPrivateFunctionCallImpl(
|
IrPrivateFunctionCallImpl(
|
||||||
startOffset = startOffset,
|
startOffset = callee.startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = callee.endOffset,
|
||||||
type = actualType,
|
type = actualType,
|
||||||
symbol = callee.symbol,
|
valueArgumentsCount = devirtualizedCallee.parameters.size,
|
||||||
descriptor = callee.descriptor,
|
virtualCallee = callee,
|
||||||
typeArgumentsCount = callee.typeArgumentsCount,
|
dfgSymbol = devirtualizedCallee,
|
||||||
dfgSymbol = devirtualizedCallee,
|
moduleDescriptor = devirtualizedCallee.module.descriptor,
|
||||||
totalFunctions = devirtualizedCallee.module.numberOfFunctions,
|
totalFunctions = devirtualizedCallee.module.numberOfFunctions,
|
||||||
moduleDescriptor = devirtualizedCallee.module.descriptor,
|
functionIndex = devirtualizedCallee.symbolTableIndex
|
||||||
functionIndex = devirtualizedCallee.symbolTableIndex,
|
|
||||||
virtualCallee = callee
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
||||||
actualCallee: DataFlowIR.FunctionSymbol.Declared,
|
actualCallee: DataFlowIR.FunctionSymbol.Declared,
|
||||||
receiver: IrVariable,
|
parameters: List<PossiblyCoercedValue>) =
|
||||||
extensionReceiver: PossiblyCoercedValue?,
|
|
||||||
parameters: Map<ValueParameterDescriptor, PossiblyCoercedValue>) =
|
|
||||||
actualCallee.bridgeTarget.let {
|
actualCallee.bridgeTarget.let {
|
||||||
// if (it == null)
|
if (it == null)
|
||||||
irDevirtualizedCall(callee, actualType, actualCallee).apply {
|
irDevirtualizedCall(callee, actualType, actualCallee).apply {
|
||||||
this.dispatchReceiver = irGet(receiver)
|
parameters.forEachIndexed { index, value ->
|
||||||
this.extensionReceiver = extensionReceiver?.getFullValue(this@irDevirtualizedCall)
|
putValueArgument(index, value.getFullValue(this@irDevirtualizedCall))
|
||||||
callee.descriptor.valueParameters.forEach {
|
|
||||||
putValueArgument(it.index, parameters[it]!!.getFullValue(this@irDevirtualizedCall))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
else {
|
else {
|
||||||
val bridgeTarget = it.resolved() as DataFlowIR.FunctionSymbol.Declared
|
val bridgeTarget = it.resolved() as DataFlowIR.FunctionSymbol.Declared
|
||||||
val callResult = irDevirtualizedCall(callee, actualType, bridgeTarget).apply {
|
val callResult = irDevirtualizedCall(callee, actualType, bridgeTarget).apply {
|
||||||
this.dispatchReceiver = irGet(receiver)
|
parameters.forEachIndexed { index, value ->
|
||||||
this.extensionReceiver = extensionReceiver?.let {
|
putValueArgument(index, irCoerceIfNeeded(
|
||||||
irCoerceIfNeeded(
|
type = actualCallee.parameters[index],
|
||||||
type = actualCallee.parameterTypes[1].resolved(),
|
targetType = bridgeTarget.parameters[index],
|
||||||
targetType = bridgeTarget.parameterTypes[1].resolved(),
|
possiblyCoercedValue = value
|
||||||
possiblyCoercedValue = it
|
))
|
||||||
)
|
|
||||||
}
|
|
||||||
val startIndex = if (extensionReceiver == null) 1 else 2
|
|
||||||
callee.descriptor.valueParameters.forEach {
|
|
||||||
this.putValueArgument(it.index,
|
|
||||||
irCoerceIfNeeded(
|
|
||||||
type = actualCallee.parameterTypes[startIndex + it.index].resolved(),
|
|
||||||
targetType = bridgeTarget.parameterTypes[startIndex + it.index].resolved(),
|
|
||||||
possiblyCoercedValue = parameters[it]!!
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val returnCoercion = context.ir.symbols.getTypeConversion(
|
val returnCoercion = getTypeConversion(bridgeTarget.returnParameter, actualCallee.returnParameter)
|
||||||
bridgeTarget.returnType.resolved().correspondingValueType,
|
irCoerce(callResult, returnCoercion?.coerceFunction)
|
||||||
actualCallee.returnType.resolved().correspondingValueType)
|
|
||||||
irCoerce(callResult, returnCoercion)
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
irModule.transformChildrenVoid(object: IrElementTransformerVoidWithContext() {
|
irModule.transformChildrenVoid(object: IrElementTransformerVoidWithContext() {
|
||||||
@@ -1160,12 +1151,10 @@ internal object Devirtualization {
|
|||||||
arg.argument
|
arg.argument
|
||||||
else arg
|
else arg
|
||||||
if (!uncastedArg.isBoxOrUnboxCall()) return expression
|
if (!uncastedArg.isBoxOrUnboxCall()) return expression
|
||||||
/*
|
|
||||||
val argarg = (uncastedArg as IrCall).getArguments().single().second
|
val argarg = (uncastedArg as IrCall).getArguments().single().second
|
||||||
if (boxFunctions[expression.symbol].let { it != null && it == unboxFunctions[uncastedArg.symbol] }
|
if (expression.symbol.owner.returnType == uncastedArg.symbol.owner.explicitParameters.single().type
|
||||||
|| unboxFunctions[expression.symbol].let { it != null && it == boxFunctions[uncastedArg.symbol] })
|
&& expression.symbol.owner.explicitParameters.single().type == uncastedArg.symbol.owner.returnType)
|
||||||
return argarg
|
return argarg
|
||||||
*/
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1209,27 +1198,19 @@ internal object Devirtualization {
|
|||||||
optimize && 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
|
||||||
irBlock(expression) {
|
irBlock(expression) {
|
||||||
val receiver = irTemporary(dispatchReceiver, "receiver")
|
val parameters = expression.getArgumentsWithSymbols().mapIndexed { index, arg ->
|
||||||
val extensionReceiver = expression.extensionReceiver?.let {
|
irSplitCoercion(arg.second, "arg$index", arg.first.owner.type)
|
||||||
irSplitCoercion(it, "extensionReceiver", function.extensionReceiverParameter!!.type)
|
|
||||||
}
|
}
|
||||||
val parameters = expression.descriptor.valueParameters.associate {
|
+irDevirtualizedCall(expression, type, actualCallee, parameters)
|
||||||
it to irSplitCoercion(expression.getValueArgument(it)!!, "arg${it.index}", function.valueParameters[it.index].type)
|
|
||||||
}
|
|
||||||
+irDevirtualizedCall(expression, type, actualCallee, receiver, extensionReceiver, parameters)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> irBlock(expression) {
|
else -> irBlock(expression) {
|
||||||
val receiver = irTemporary(dispatchReceiver, "receiver")
|
val parameters = expression.getArgumentsWithSymbols().mapIndexed { index, arg ->
|
||||||
val extensionReceiver = expression.extensionReceiver?.let {
|
irSplitCoercion(arg.second, "arg$index", arg.first.owner.type)
|
||||||
irSplitCoercion(it, "extensionReceiver", function.extensionReceiverParameter!!.type)
|
|
||||||
}
|
|
||||||
val parameters = expression.descriptor.valueParameters.associate {
|
|
||||||
it to irSplitCoercion(expression.getValueArgument(it)!!, "arg${it.index}", function.valueParameters[it.index].type)
|
|
||||||
}
|
}
|
||||||
val typeInfo = irTemporary(irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
val typeInfo = irTemporary(irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
||||||
putValueArgument(0, irGet(receiver))
|
putValueArgument(0, parameters[0].getFullValue(this@irBlock))
|
||||||
})
|
})
|
||||||
|
|
||||||
val branches = mutableListOf<IrBranchImpl>()
|
val branches = mutableListOf<IrBranchImpl>()
|
||||||
@@ -1241,7 +1222,7 @@ internal object Devirtualization {
|
|||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.ir.symbols.nativePtrType,
|
type = context.ir.symbols.nativePtrType,
|
||||||
symbol = dispatchReceiver.type.getErasedTypeClass(),
|
symbol = dispatchReceiver.type.getErasedTypeClass(),
|
||||||
classType = receiver.type,
|
classType = dispatchReceiver.type,
|
||||||
moduleDescriptor = actualReceiverType.module!!.descriptor,
|
moduleDescriptor = actualReceiverType.module!!.descriptor,
|
||||||
totalClasses = actualReceiverType.module.numberOfClasses,
|
totalClasses = actualReceiverType.module.numberOfClasses,
|
||||||
classIndex = actualReceiverType.symbolTableIndex,
|
classIndex = actualReceiverType.symbolTableIndex,
|
||||||
@@ -1258,7 +1239,7 @@ internal object Devirtualization {
|
|||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
condition = condition,
|
condition = condition,
|
||||||
result = irDevirtualizedCall(expression, type, actualCallee, receiver, extensionReceiver, parameters)
|
result = irDevirtualizedCall(expression, type, actualCallee, parameters)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!optimize) { // Add else branch throwing exception for debug purposes.
|
if (!optimize) { // Add else branch throwing exception for debug purposes.
|
||||||
|
|||||||
+3
-4
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.konan.DirectedGraphMultiNode
|
|||||||
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
|
||||||
|
|
||||||
internal object EscapeAnalysis {
|
internal object EscapeAnalysis {
|
||||||
|
|
||||||
@@ -283,7 +282,7 @@ internal object EscapeAnalysis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (functionSymbol in callGraph.directEdges.keys) {
|
for (functionSymbol in callGraph.directEdges.keys) {
|
||||||
val numberOfParameters = functionSymbol.parameterTypes.size
|
val numberOfParameters = functionSymbol.parameters.size
|
||||||
escapeAnalysisResults[functionSymbol] = FunctionEscapeAnalysisResult(
|
escapeAnalysisResults[functionSymbol] = FunctionEscapeAnalysisResult(
|
||||||
// Assume no edges at the beginning.
|
// Assume no edges at the beginning.
|
||||||
// Then iteratively add needed.
|
// Then iteratively add needed.
|
||||||
@@ -396,7 +395,7 @@ internal object EscapeAnalysis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getConservativeFunctionEAResult(symbol: DataFlowIR.FunctionSymbol): FunctionEscapeAnalysisResult {
|
private fun getConservativeFunctionEAResult(symbol: DataFlowIR.FunctionSymbol): FunctionEscapeAnalysisResult {
|
||||||
val numberOfParameters = symbol.parameterTypes.size
|
val numberOfParameters = symbol.parameters.size
|
||||||
return FunctionEscapeAnalysisResult((0..numberOfParameters).map {
|
return FunctionEscapeAnalysisResult((0..numberOfParameters).map {
|
||||||
ParameterEscapeAnalysisResult(
|
ParameterEscapeAnalysisResult(
|
||||||
escapes = true,
|
escapes = true,
|
||||||
@@ -425,7 +424,7 @@ internal object EscapeAnalysis {
|
|||||||
|
|
||||||
FunctionEscapeAnalysisResult.fromBits(
|
FunctionEscapeAnalysisResult.fromBits(
|
||||||
callee.escapes ?: 0,
|
callee.escapes ?: 0,
|
||||||
(0..callee.parameterTypes.size).map { callee.pointsTo?.elementAtOrNull(it) ?: 0 }
|
(0..callee.parameters.size).map { callee.pointsTo?.elementAtOrNull(it) ?: 0 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user