[IR] Combine IrInterpreterNameCheck with common one
This way we achieve faster compilation time. We want to traverse IR tree as little as possible. If we add new checker than the time to evaluate constants basically doubles. #KT-58923
This commit is contained in:
+4
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.interpreter.accessesTopLevelOrObjectField
|
import org.jetbrains.kotlin.ir.interpreter.accessesTopLevelOrObjectField
|
||||||
import org.jetbrains.kotlin.ir.interpreter.fqName
|
import org.jetbrains.kotlin.ir.interpreter.fqName
|
||||||
import org.jetbrains.kotlin.ir.interpreter.isAccessToNotNullableObject
|
import org.jetbrains.kotlin.ir.interpreter.isAccessToNotNullableObject
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor.Companion.isEnumName
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor.Companion.isKCallableNameCall
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
@@ -61,6 +63,8 @@ class IrInterpreterCommonChecker : IrInterpreterChecker {
|
|||||||
val owner = expression.symbol.owner
|
val owner = expression.symbol.owner
|
||||||
if (!data.mode.canEvaluateFunction(owner)) return false
|
if (!data.mode.canEvaluateFunction(owner)) return false
|
||||||
|
|
||||||
|
if (expression.isKCallableNameCall(data.irBuiltIns) || expression.isEnumName()) return true
|
||||||
|
|
||||||
if (expression.dispatchReceiver.isAccessToNotNullableObject()) {
|
if (expression.dispatchReceiver.isAccessToNotNullableObject()) {
|
||||||
return expression.isGetterToConstVal()
|
return expression.isGetterToConstVal()
|
||||||
}
|
}
|
||||||
|
|||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.checker
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.property
|
|
||||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
|
||||||
|
|
||||||
class IrInterpreterNameChecker : IrInterpreterChecker {
|
|
||||||
override fun visitElement(element: IrElement, data: IrInterpreterCheckerData) = false
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: IrInterpreterCheckerData): Boolean {
|
|
||||||
val owner = expression.symbol.owner
|
|
||||||
if (!data.mode.canEvaluateFunction(owner)) return false
|
|
||||||
|
|
||||||
return expression.isKCallableNameCall(data.irBuiltIns) || expression.isEnumName()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: IrInterpreterCheckerData): Boolean {
|
|
||||||
val possibleNameCall = expression.arguments.singleOrNull() as? IrCall ?: return false
|
|
||||||
return possibleNameCall.accept(this, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun IrCall.isKCallableNameCall(irBuiltIns: IrBuiltIns): Boolean {
|
|
||||||
if (this.dispatchReceiver !is IrCallableReference<*>) return false
|
|
||||||
|
|
||||||
val directMember = this.symbol.owner.let { it.property ?: it }
|
|
||||||
|
|
||||||
val irClass = directMember.parent as? IrClass ?: return false
|
|
||||||
if (!irClass.isSubclassOf(irBuiltIns.kCallableClass.owner)) return false
|
|
||||||
|
|
||||||
val name = when (directMember) {
|
|
||||||
is IrSimpleFunction -> directMember.name
|
|
||||||
is IrProperty -> directMember.name
|
|
||||||
else -> throw AssertionError("Should be IrSimpleFunction or IrProperty, got $directMember")
|
|
||||||
}
|
|
||||||
return name.asString() == "name"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrCall.isEnumName(): Boolean {
|
|
||||||
val owner = this.symbol.owner
|
|
||||||
if (owner.extensionReceiverParameter != null || owner.valueParameters.isNotEmpty()) return false
|
|
||||||
val property = owner.property ?: return false
|
|
||||||
return this.dispatchReceiver is IrGetEnumValue && property.name.asString() == "name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+32
-1
@@ -5,12 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.preprocessor
|
package org.jetbrains.kotlin.ir.interpreter.preprocessor
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterNameChecker.Companion.isKCallableNameCall
|
import org.jetbrains.kotlin.ir.interpreter.property
|
||||||
|
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
|
||||||
// Note: this class still will not allow us to evaluate things like `A()::a.name + `A()::b.name`.
|
// Note: this class still will not allow us to evaluate things like `A()::a.name + `A()::b.name`.
|
||||||
@@ -33,4 +39,29 @@ class IrInterpreterKCallableNamePreprocessor : IrInterpreterPreprocessor {
|
|||||||
expression.startOffset, expression.endOffset, expression.type, origin = null, statements = listOf(receiver, expression)
|
expression.startOffset, expression.endOffset, expression.type, origin = null, statements = listOf(receiver, expression)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun IrCall.isKCallableNameCall(irBuiltIns: IrBuiltIns): Boolean {
|
||||||
|
if (this.dispatchReceiver !is IrCallableReference<*>) return false
|
||||||
|
|
||||||
|
val directMember = this.symbol.owner.let { it.property ?: it }
|
||||||
|
|
||||||
|
val irClass = directMember.parent as? IrClass ?: return false
|
||||||
|
if (!irClass.isSubclassOf(irBuiltIns.kCallableClass.owner)) return false
|
||||||
|
|
||||||
|
val name = when (directMember) {
|
||||||
|
is IrSimpleFunction -> directMember.name
|
||||||
|
is IrProperty -> directMember.name
|
||||||
|
else -> throw AssertionError("Should be IrSimpleFunction or IrProperty, got $directMember")
|
||||||
|
}
|
||||||
|
return name.asString() == "name"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrCall.isEnumName(): Boolean {
|
||||||
|
val owner = this.symbol.owner
|
||||||
|
if (owner.extensionReceiverParameter != null || owner.valueParameters.isNotEmpty()) return false
|
||||||
|
val property = owner.property ?: return false
|
||||||
|
return this.dispatchReceiver is IrGetEnumValue && property.name.asString() == "name"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+12
-18
@@ -38,25 +38,19 @@ fun IrFile.transformConst(
|
|||||||
preprocessor.preprocess(file, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
preprocessor.preprocess(file, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
||||||
}
|
}
|
||||||
|
|
||||||
val checkers = setOf(
|
val checker = IrInterpreterCommonChecker()
|
||||||
IrInterpreterNameChecker(),
|
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||||
IrInterpreterCommonChecker(),
|
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||||
)
|
)
|
||||||
|
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||||
checkers.fold(preprocessedFile) { file, checker ->
|
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
)
|
||||||
interpreter, file, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||||
)
|
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
)
|
||||||
interpreter, file, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||||
)
|
preprocessedFile.transform(irConstDeclarationAnnotationTransformer, null)
|
||||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
preprocessedFile.transform(irConstTypeAnnotationTransformer, null)
|
||||||
interpreter, file, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
|
||||||
)
|
|
||||||
file.transform(irConstExpressionTransformer, null)
|
|
||||||
file.transform(irConstDeclarationAnnotationTransformer, null)
|
|
||||||
file.transform(irConstTypeAnnotationTransformer, null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
|
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ const val methodName = A::foo.<!EVALUATED("foo")!>name<!>
|
|||||||
const val suspendMethodName = A::bar.<!EVALUATED("bar")!>name<!>
|
const val suspendMethodName = A::bar.<!EVALUATED("bar")!>name<!>
|
||||||
const val className = ::A.<!EVALUATED("<init>")!>name<!>
|
const val className = ::A.<!EVALUATED("<init>")!>name<!>
|
||||||
const val topLevelPropName = ::topLevelProp.<!EVALUATED("topLevelProp")!>name<!>
|
const val topLevelPropName = ::topLevelProp.<!EVALUATED("topLevelProp")!>name<!>
|
||||||
const val nameInComplexExpression = A::OK.<!EVALUATED("OK")!>name<!> <!EVALUATED("OK!")!>+ "!"<!>
|
const val nameInComplexExpression = A::OK.name <!EVALUATED("OK!")!>+ "!"<!>
|
||||||
|
|
||||||
// STOP_EVALUATION_CHECKS
|
// STOP_EVALUATION_CHECKS
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -27,7 +27,7 @@ class A {
|
|||||||
val insideStringConcat = "${temp::b.<!EVALUATED("b")!>name<!>}"
|
val insideStringConcat = "${temp::b.<!EVALUATED("b")!>name<!>}"
|
||||||
|
|
||||||
val complexExpression1 = A()::a.<!EVALUATED("a")!>name<!> + A()::b.<!EVALUATED("b")!>name<!>
|
val complexExpression1 = A()::a.<!EVALUATED("a")!>name<!> + A()::b.<!EVALUATED("b")!>name<!>
|
||||||
val complexExpression2 = A::a.<!EVALUATED("a")!>name<!> <!EVALUATED("ab")!>+ A::b.<!EVALUATED("b")!>name<!><!>
|
val complexExpression2 = A::a.name <!EVALUATED("ab")!>+ A::b.name<!>
|
||||||
|
|
||||||
var recursive = ::test.<!EVALUATED("test")!>name<!>
|
var recursive = ::test.<!EVALUATED("test")!>name<!>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user