JVM_IR: extract boolean-valued DFS on IR elements into a helper
This commit is contained in:
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
|||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
@@ -404,3 +405,15 @@ fun IrFile.getKtFile(): KtFile? =
|
|||||||
|
|
||||||
fun IrType.isInlineClassType(): Boolean =
|
fun IrType.isInlineClassType(): Boolean =
|
||||||
erasedUpperBound.isInline
|
erasedUpperBound.isInline
|
||||||
|
|
||||||
|
inline fun IrElement.hasChild(crossinline block: (IrElement) -> Boolean): Boolean {
|
||||||
|
var result = false
|
||||||
|
acceptChildren(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) = when {
|
||||||
|
result -> Unit
|
||||||
|
block(element) -> result = true
|
||||||
|
else -> element.acceptChildren(this, null)
|
||||||
|
}
|
||||||
|
}, null)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
+6
-21
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.parentClassId
|
import org.jetbrains.kotlin.backend.jvm.codegen.parentClassId
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.hasChild
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.irArrayOf
|
import org.jetbrains.kotlin.backend.jvm.ir.irArrayOf
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.needsAccessor
|
import org.jetbrains.kotlin.backend.jvm.ir.needsAccessor
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.calculateOwner
|
import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.calculateOwner
|
||||||
@@ -28,7 +29,6 @@ import org.jetbrains.kotlin.codegen.inline.loadCompiledInlineFunction
|
|||||||
import org.jetbrains.kotlin.codegen.optimization.nullCheck.usesLocalExceptParameterNullCheck
|
import org.jetbrains.kotlin.codegen.optimization.nullCheck.usesLocalExceptParameterNullCheck
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
@@ -47,7 +47,6 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
|||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -274,17 +273,7 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
|||||||
return loadCompiledInlineFunction(containerId, signature.asmMethod, isSuspend, hasMangledReturnType, context.state)
|
return loadCompiledInlineFunction(containerId, signature.asmMethod, isSuspend, hasMangledReturnType, context.state)
|
||||||
.node.usesLocalExceptParameterNullCheck(localIndex)
|
.node.usesLocalExceptParameterNullCheck(localIndex)
|
||||||
}
|
}
|
||||||
|
return hasChild { it is IrGetValue && it.symbol == valueParameters[index].symbol }
|
||||||
var result = false
|
|
||||||
accept(object : IrElementVisitorVoid {
|
|
||||||
override fun visitElement(element: IrElement) =
|
|
||||||
if (result) Unit else element.acceptChildren(this, null)
|
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue) {
|
|
||||||
if (expression.symbol == valueParameters[index].symbol) result = true
|
|
||||||
}
|
|
||||||
}, null)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assuming that the only functions that take PROPERTY_REFERENCE_FOR_DELEGATE-kind references are getValue,
|
// Assuming that the only functions that take PROPERTY_REFERENCE_FOR_DELEGATE-kind references are getValue,
|
||||||
@@ -292,18 +281,14 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
|||||||
private val usesPropertyParameterCache = ConcurrentHashMap<IrSymbol, Boolean>()
|
private val usesPropertyParameterCache = ConcurrentHashMap<IrSymbol, Boolean>()
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (!expression.symbol.owner.isInline) {
|
// Don't generate entries in `$$delegatedProperties` if they won't be used for anything. This is only possible
|
||||||
// Can't optimize if the function can start using the reference later.
|
// for inline functions, since for non-inline ones we need to provide some non-null value, and if they're not
|
||||||
// TODO: optimize if callee is in the same file? this requires removing the null check from it,
|
// in the same file, they can start using it without forcing a recompilation of this file.
|
||||||
// or at least providing *some* non-null fake property value.
|
if (!expression.symbol.owner.isInline) return super.visitCall(expression)
|
||||||
return super.visitCall(expression)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index in expression.symbol.owner.valueParameters.indices) {
|
for (index in expression.symbol.owner.valueParameters.indices) {
|
||||||
val value = expression.getValueArgument(index)
|
val value = expression.getValueArgument(index)
|
||||||
if (value is IrCallableReference<*> && value.origin == IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE) {
|
if (value is IrCallableReference<*> && value.origin == IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE) {
|
||||||
if (!usesPropertyParameterCache.getOrPut(expression.symbol) { expression.symbol.owner.usesParameter(index) }) {
|
if (!usesPropertyParameterCache.getOrPut(expression.symbol) { expression.symbol.owner.usesParameter(index) }) {
|
||||||
// Don't generate an entry in `$$delegatedProperties`, it won't be used anyway.
|
|
||||||
expression.putValueArgument(index, IrConstImpl.constNull(value.startOffset, value.endOffset, value.type))
|
expression.putValueArgument(index, IrConstImpl.constNull(value.startOffset, value.endOffset, value.type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-19
@@ -10,11 +10,13 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.*
|
import org.jetbrains.kotlin.backend.common.ir.*
|
||||||
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
|
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isReadOfCrossinline
|
import org.jetbrains.kotlin.backend.jvm.codegen.isReadOfCrossinline
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
|
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.hasChild
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_LABEL_FIELD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_LABEL_FIELD_NAME
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME
|
||||||
@@ -47,25 +49,8 @@ internal val suspendLambdaPhase = makeIrFilePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private fun IrFunction.capturesCrossinline(): Boolean {
|
private fun IrFunction.capturesCrossinline(): Boolean {
|
||||||
var result = false
|
val parents = parents.toSet()
|
||||||
accept(object : IrElementVisitorVoid {
|
return hasChild { it is IrGetValue && it.isReadOfCrossinline() && it.symbol.owner.parent in parents }
|
||||||
override fun visitElement(element: IrElement) {
|
|
||||||
if (!result) element.acceptChildren(this, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction) {
|
|
||||||
functions.add(declaration)
|
|
||||||
super.visitFunction(declaration)
|
|
||||||
functions.remove(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue) {
|
|
||||||
result = result || (expression.isReadOfCrossinline() && expression.symbol.owner.parent !in functions)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val functions = mutableSetOf<IrFunction>()
|
|
||||||
}, null)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class SuspendLoweringUtils(protected val context: JvmBackendContext) {
|
internal abstract class SuspendLoweringUtils(protected val context: JvmBackendContext) {
|
||||||
|
|||||||
Reference in New Issue
Block a user