Change the way of receiving fields

Before that, interpreted values for fields were taken by backing
field's symbol. For now, they will be taken by property's symbol.
It was done because not all properties contain backing field. For
example, Throwable class in FIR2IR.
This commit is contained in:
Ivan Kylchik
2020-06-10 15:36:51 +03:00
parent 8644c48b28
commit 3155f56d8a
2 changed files with 19 additions and 20 deletions
@@ -337,7 +337,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
val receiver = irClass.thisReceiver!!.symbol val receiver = irClass.thisReceiver!!.symbol
if (property.backingField?.initializer != null) { if (property.backingField?.initializer != null) {
val receiverState = stack.getVariable(receiver).state val receiverState = stack.getVariable(receiver).state
val propertyVar = Variable(property.backingField!!.symbol, stack.popReturnValue()) val propertyVar = Variable(property.symbol, stack.popReturnValue())
receiverState.setField(propertyVar) receiverState.setField(propertyVar)
} }
} }
@@ -508,7 +508,8 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
// receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend // receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend
val receiver = (expression.receiver as IrDeclarationReference).symbol val receiver = (expression.receiver as IrDeclarationReference).symbol
stack.getVariable(receiver).apply { this.state.setField(Variable(expression.symbol, stack.popReturnValue())) } val propertySymbol = expression.symbol.owner.correspondingPropertySymbol!!
stack.getVariable(receiver).apply { this.state.setField(Variable(propertySymbol, stack.popReturnValue())) }
return Next return Next
} }
@@ -521,7 +522,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next return Next
} }
// receiver is null, for example, for top level fields // receiver is null, for example, for top level fields
val result = receiver?.let { stack.getVariable(receiver).state.getState(expression.symbol) } val result = receiver?.let { stack.getVariable(receiver).state.getState(field.correspondingPropertySymbol!!) }
?: return (expression.symbol.owner.initializer?.expression?.interpret() ?: Next) ?: return (expression.symbol.owner.initializer?.expression?.interpret() ?: Next)
stack.pushReturnValue(result) stack.pushReturnValue(result)
return Next return Next
@@ -672,12 +673,11 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
"UByteArray", "UShortArray", "UIntArray", "ULongArray" -> { "UByteArray", "UShortArray", "UIntArray", "ULongArray" -> {
val owner = expression.type.classOrNull!!.owner val owner = expression.type.classOrNull!!.owner
val storageProperty = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "storage" } val storageProperty = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "storage" }
val storageField = storageProperty.backingField!!
val primitiveArray = args.map { ((it as Common).fields.single().state as Primitive<*>).value } val primitiveArray = args.map { ((it as Common).fields.single().state as Primitive<*>).value }
val unsignedArray = primitiveArray.toPrimitiveStateArray(storageField.type) val unsignedArray = primitiveArray.toPrimitiveStateArray(storageProperty.backingField!!.type)
Common(owner).apply { Common(owner).apply {
setSuperClassRecursive() setSuperClassRecursive()
fields.add(Variable(storageField.symbol, unsignedArray)) fields.add(Variable(storageProperty.symbol, unsignedArray))
} }
} }
else -> args.toPrimitiveStateArray(expression.type) else -> args.toPrimitiveStateArray(expression.type)
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
import org.jetbrains.kotlin.backend.common.interpreter.toState import org.jetbrains.kotlin.backend.common.interpreter.toState
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.isSubclassOf import org.jetbrains.kotlin.ir.util.isSubclassOf
@@ -22,15 +21,15 @@ class ExceptionState private constructor(
private lateinit var exceptionFqName: String private lateinit var exceptionFqName: String
private val exceptionHierarchy = mutableListOf<String>() private val exceptionHierarchy = mutableListOf<String>()
private val messageField = irClass.getFieldByName("message") private val messageProperty = irClass.getPropertyByName("message")
private val causeField = irClass.getFieldByName("cause") private val causeProperty = irClass.getPropertyByName("cause")
private val stackTrace: List<String> = stackTrace.reversed() private val stackTrace: List<String> = stackTrace.reversed()
init { init {
if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName() if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName()
if (fields.none { it.symbol == messageField.symbol }) { if (fields.none { it.symbol == messageProperty.symbol }) {
setMessage() setMessage()
} }
} }
@@ -81,17 +80,17 @@ class ExceptionState private constructor(
} }
private fun setMessage(messageValue: String? = null) { private fun setMessage(messageValue: String? = null) {
setField(Variable(messageField.symbol, Primitive(messageValue, messageField.type))) setField(Variable(messageProperty.symbol, Primitive(messageValue, messageProperty.getter!!.returnType)))
} }
private fun setCause(causeValue: State?) { private fun setCause(causeValue: State?) {
setField(Variable(causeField.symbol, causeValue ?: Primitive<Throwable?>(null, causeField.type))) setField(Variable(causeProperty.symbol, causeValue ?: Primitive<Throwable?>(null, causeProperty.getter!!.returnType)))
} }
fun getMessage(): String? = (getState(messageField.symbol) as Primitive<*>).value as String? fun getMessage(): String? = (getState(messageProperty.symbol) as Primitive<*>).value as String?
private fun getMessageWithName(): String = getMessage()?.let { "$exceptionFqName: $it" } ?: exceptionFqName private fun getMessageWithName(): String = getMessage()?.let { "$exceptionFqName: $it" } ?: exceptionFqName
fun getCause(): ExceptionState? = getState(causeField.symbol)?.let { if (it is ExceptionState) it else null } fun getCause(): ExceptionState? = getState(causeProperty.symbol)?.let { if (it is ExceptionState) it else null }
fun getFullDescription(): String { fun getFullDescription(): String {
// TODO remainder of the stack trace with "..." // TODO remainder of the stack trace with "..."
@@ -107,18 +106,18 @@ class ExceptionState private constructor(
fun getThisAsCauseForException() = ExceptionData(this) fun getThisAsCauseForException() = ExceptionData(this)
companion object { companion object {
private fun IrClass.getFieldByName(name: String): IrField { private fun IrClass.getPropertyByName(name: String): IrProperty {
val property = this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty val property = this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty
return (property.getter!!.getLastOverridden() as IrSimpleFunction).correspondingPropertySymbol!!.owner.backingField!! return (property.getter!!.getLastOverridden() as IrSimpleFunction).correspondingPropertySymbol!!.owner
} }
private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List<String>): MutableList<Variable> { private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List<String>): MutableList<Variable> {
val messageField = irClass.getFieldByName("message") val messageProperty = irClass.getPropertyByName("message")
val causeField = irClass.getFieldByName("cause") val causeProperty = irClass.getPropertyByName("cause")
val messageVar = Variable(messageField.symbol, exception.message.toState(messageField.type)) val messageVar = Variable(messageProperty.symbol, exception.message.toState(messageProperty.getter!!.returnType))
val causeVar = exception.cause?.let { val causeVar = exception.cause?.let {
Variable(causeField.symbol, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" })) Variable(causeProperty.symbol, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" }))
} }
return listOfNotNull(messageVar, causeVar).toMutableList() return listOfNotNull(messageVar, causeVar).toMutableList()
} }