Add support in interpreter for jvm static fields in primitive classes

This commit is contained in:
Ivan Kylchik
2020-06-10 23:41:10 +03:00
parent a3c77eca08
commit db5046af85
3 changed files with 30 additions and 13 deletions
@@ -14,11 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isLocal
import org.jetbrains.kotlin.ir.util.isObject
import org.jetbrains.kotlin.ir.util.statements
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.FqName
@@ -159,8 +155,20 @@ class IrCompileTimeChecker(
}
override fun visitGetField(expression: IrGetField, data: Nothing?): Boolean {
val parent = expression.symbol.owner.parent as IrSymbolOwner
return callStack.contains(parent.symbol)
val owner = expression.symbol.owner
val parent = owner.parent as IrSymbolOwner
val isJavaPrimitiveStatic = owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
owner.parentAsClass.fqNameWhenAvailable.isJavaPrimitive()
return callStack.contains(parent.symbol) || isJavaPrimitiveStatic
}
// TODO find similar method in utils
private fun FqName?.isJavaPrimitive(): Boolean {
this ?: return false
return this.toString() in setOf(
"java.lang.Byte", "java.lang.Short", "java.lang.Integer", "java.lang.Long",
"java.lang.Float", "java.lang.Double", "java.lang.Boolean", "java.lang.Character"
)
}
override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.common.interpreter.exceptions.InterpreterTim
import org.jetbrains.kotlin.backend.common.interpreter.intrinsics.IntrinsicEvaluator
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
import org.jetbrains.kotlin.backend.common.interpreter.state.*
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
@@ -389,7 +388,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
private suspend fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall): ExecutionResult {
if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
if (delegatingConstructorCall.symbol.owner.parent == irBuiltIns.anyClass.owner) {
val anyAsStateObject = Common(irBuiltIns.anyClass.owner)
stack.pushReturnValue(anyAsStateObject)
return Next
@@ -506,6 +505,12 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
private suspend fun interpretGetField(expression: IrGetField): ExecutionResult {
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor
val field = expression.symbol.owner
// for java static variables
if (field.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && field.isStatic) {
stack.pushReturnValue(Wrapper.getStaticGetter(field)!!.invokeWithArguments().toState(field.type))
return Next
}
// receiver is null, for example, for top level fields
val result = receiver?.let { stack.getVariable(receiver).state.getState(expression.symbol.descriptor) }
?: return (expression.symbol.owner.initializer?.expression?.interpret() ?: Next)
@@ -14,15 +14,13 @@ import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.isTypeParameter
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithDifferentJvmName
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties
import org.jetbrains.kotlin.name.FqNameUnsafe
@@ -97,6 +95,12 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
return MethodHandles.lookup().findStatic(jvmClassName, irFunction.name.asString(), methodType)
}
fun getStaticGetter(field: IrField): MethodHandle? {
val jvmClass = field.parentAsClass.defaultType.getClass(true)
val returnType = field.type.getClass(false)
return MethodHandles.lookup().findStaticGetter(jvmClass, field.name.asString(), returnType)
}
fun getEnumEntry(enumClass: IrClass): MethodHandle? {
val intrinsicName = enumClass.getEvaluateIntrinsicValue()
if (intrinsicName?.isEmpty() == true) return null