[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.fqName
|
||||
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.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
@@ -61,6 +63,8 @@ class IrInterpreterCommonChecker : IrInterpreterChecker {
|
||||
val owner = expression.symbol.owner
|
||||
if (!data.mode.canEvaluateFunction(owner)) return false
|
||||
|
||||
if (expression.isKCallableNameCall(data.irBuiltIns) || expression.isEnumName()) return true
|
||||
|
||||
if (expression.dispatchReceiver.isAccessToNotNullableObject()) {
|
||||
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
|
||||
|
||||
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.IrGetValue
|
||||
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
|
||||
|
||||
// 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)
|
||||
)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
val checkers = setOf(
|
||||
IrInterpreterNameChecker(),
|
||||
IrInterpreterCommonChecker(),
|
||||
val checker = IrInterpreterCommonChecker()
|
||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
|
||||
checkers.fold(preprocessedFile) { file, checker ->
|
||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||
interpreter, file, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||
interpreter, file, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||
interpreter, file, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
file.transform(irConstExpressionTransformer, null)
|
||||
file.transform(irConstDeclarationAnnotationTransformer, null)
|
||||
file.transform(irConstTypeAnnotationTransformer, null)
|
||||
}
|
||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||
preprocessedFile.transform(irConstDeclarationAnnotationTransformer, null)
|
||||
preprocessedFile.transform(irConstTypeAnnotationTransformer, null)
|
||||
}
|
||||
|
||||
// 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 className = ::A.<!EVALUATED("<init>")!>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
|
||||
fun box(): String {
|
||||
|
||||
Vendored
+1
-1
@@ -27,7 +27,7 @@ class A {
|
||||
val insideStringConcat = "${temp::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<!>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user