Rewrite Complex class as interface
This change allow ExceptionState to be both: State and Throwable
This commit is contained in:
committed by
TeamCityServer
parent
6808151af7
commit
1d0acedc48
@@ -150,7 +150,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
|
||||
internal fun State.wrapAsProxyIfNeeded(calledFromBuiltIns: Boolean = false): Any? {
|
||||
return when (this) {
|
||||
is ExceptionState -> this.getThisAsCauseForException()
|
||||
is ExceptionState -> this
|
||||
is Wrapper -> this.value
|
||||
is Primitive<*> -> this.value
|
||||
is Common -> Proxy(this, this@IrInterpreter, calledFromBuiltIns)
|
||||
@@ -812,9 +812,9 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
private fun interpretTry(expression: IrTry): ExecutionResult {
|
||||
try {
|
||||
expression.tryResult.interpret().check(ReturnLabel.EXCEPTION) { return it } // if not exception -> return
|
||||
val exception = stack.peekReturnValue() as ExceptionState
|
||||
val exception = stack.peekReturnValue()
|
||||
for (catchBlock in expression.catches) {
|
||||
if (exception.isSubtypeOf(catchBlock.catchParameter.type.classOrNull!!.owner)) {
|
||||
if (exception.isSubtypeOf(catchBlock.catchParameter.type)) {
|
||||
catchBlock.interpret().check { return it }
|
||||
return Next
|
||||
}
|
||||
|
||||
+1
-4
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.ir.interpreter.builtins
|
||||
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
|
||||
/** This file is generated by org.jetbrains.kotlin.backend.common.interpreter.builtins.GenerateBuiltInsMap.generateMap(). DO NOT MODIFY MANUALLY */
|
||||
|
||||
@@ -140,9 +139,7 @@ val unaryFunctions = mapOf<CompileTimeFunction, Function1<Any?, Any?>>(
|
||||
unaryOperation<Array<Any?>>("iterator", "Array") { a -> a.iterator() },
|
||||
unaryOperation<Any>("hashCode", "Any") { a -> a.hashCode() },
|
||||
unaryOperation<Any>("toString", "Any") { a -> a.toString() },
|
||||
unaryOperation<Any?>("CHECK_NOT_NULL", "T0?") { a -> a!! },
|
||||
unaryOperation<ExceptionState>("message", "Throwable") { a -> a.getMessage() },
|
||||
unaryOperation<ExceptionState>("cause", "Throwable") { a -> a.getCause() }
|
||||
unaryOperation<Any?>("CHECK_NOT_NULL", "T0?") { a -> a!! }
|
||||
)
|
||||
|
||||
val binaryFunctions = mapOf<CompileTimeFunction, Function2<Any?, Any?, Any?>>(
|
||||
|
||||
@@ -9,9 +9,10 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
|
||||
internal class Common private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>
|
||||
) : Complex(irClass, fields) {
|
||||
internal class Common private constructor(override val irClass: IrClass, override val fields: MutableList<Variable>) : Complex {
|
||||
override var superWrapperClass: Wrapper? = null
|
||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||
override var outerClass: Variable? = null
|
||||
|
||||
constructor(irClass: IrClass) : this(irClass, mutableListOf())
|
||||
|
||||
|
||||
+10
-7
@@ -14,16 +14,15 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.types.isAny
|
||||
import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal abstract class Complex(override val irClass: IrClass, override val fields: MutableList<Variable>) : State {
|
||||
var superWrapperClass: Wrapper? = null
|
||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||
var outerClass: Variable? = null
|
||||
internal interface Complex: State {
|
||||
var superWrapperClass: Wrapper?
|
||||
override val typeArguments: MutableList<Variable>
|
||||
var outerClass: Variable?
|
||||
|
||||
fun irClassFqName(): String {
|
||||
return irClass.fqNameForIrSerialization.toString()
|
||||
@@ -34,7 +33,11 @@ internal abstract class Complex(override val irClass: IrClass, override val fiel
|
||||
val propertySetters = this.declarations.filterIsInstance<IrProperty>().mapNotNull { it.setter }
|
||||
val functions = this.declarations.filterIsInstance<IrFunction>()
|
||||
return (propertyGetters + propertySetters + functions).firstOrNull {
|
||||
if (it is IrSimpleFunction) it.overrides(symbol.owner as IrSimpleFunction) else it == symbol.owner
|
||||
val owner = symbol.owner
|
||||
when {
|
||||
it is IrSimpleFunction && owner is IrSimpleFunction -> it.overrides(owner) || owner.overrides(it)
|
||||
else -> it == symbol.owner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +49,7 @@ internal abstract class Complex(override val irClass: IrClass, override val fiel
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getOverridden(owner: IrSimpleFunction): IrSimpleFunction {
|
||||
private fun getOverridden(owner: IrSimpleFunction): IrSimpleFunction {
|
||||
if (!owner.isFakeOverride || owner.body != null || owner.parentAsClass.defaultType.isAny()) return owner
|
||||
|
||||
val overriddenOwner = owner.overriddenSymbols.singleOrNull { !it.owner.parentAsClass.isInterface }?.owner
|
||||
|
||||
+18
-20
@@ -17,7 +17,16 @@ import kotlin.math.min
|
||||
|
||||
internal class ExceptionState private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>
|
||||
) : Complex(irClass, fields) {
|
||||
) : Complex, Throwable() {
|
||||
|
||||
override var superWrapperClass: Wrapper? = null
|
||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||
override var outerClass: Variable? = null
|
||||
|
||||
override val message: String?
|
||||
get() = getState(messageProperty.symbol)?.asStringOrNull()
|
||||
override val cause: Throwable?
|
||||
get() = getState(causeProperty.symbol)?.let { if (it is ExceptionState) it else null }
|
||||
|
||||
private lateinit var exceptionFqName: String
|
||||
private val exceptionHierarchy = mutableListOf<String>()
|
||||
@@ -45,6 +54,7 @@ internal class ExceptionState private constructor(
|
||||
constructor(
|
||||
exception: Throwable, irClass: IrClass, stackTrace: List<String>
|
||||
) : this(irClass, evaluateFields(exception, irClass, stackTrace), stackTrace + evaluateAdditionalStackTrace(exception)) {
|
||||
setCause(null) // TODO check this fact
|
||||
if (irClass.name.asString() != exception::class.java.simpleName) {
|
||||
// ir class wasn't found in classpath, a stub was passed => need to save java class hierarchy
|
||||
this.exceptionFqName = exception::class.java.name
|
||||
@@ -54,18 +64,11 @@ internal class ExceptionState private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
data class ExceptionData(val state: ExceptionState) : Throwable() {
|
||||
override val message: String? = state.getMessage()
|
||||
override fun fillInStackTrace() = this
|
||||
|
||||
override fun toString(): String = state.getMessageWithName()
|
||||
}
|
||||
|
||||
private fun setUpCauseIfNeeded(wrapper: Wrapper?) {
|
||||
val cause = (wrapper?.value as? Throwable)?.cause as? ExceptionData
|
||||
setCause(cause?.state)
|
||||
if (getMessage() == null && cause != null) {
|
||||
val causeMessage = cause.state.exceptionFqName + (cause.state.getMessage()?.let { ": $it" } ?: "")
|
||||
val cause = (wrapper?.value as? Throwable)?.cause as? ExceptionState
|
||||
setCause(cause)
|
||||
if (message == null && cause != null) {
|
||||
val causeMessage = cause.exceptionFqName + (cause.message?.let { ": $it" } ?: "")
|
||||
setMessage(causeMessage)
|
||||
}
|
||||
}
|
||||
@@ -85,23 +88,18 @@ internal class ExceptionState private constructor(
|
||||
setField(Variable(causeProperty.symbol, causeValue ?: Primitive<Throwable?>(null, causeProperty.getter!!.returnType)))
|
||||
}
|
||||
|
||||
fun getMessage(): String? = (getState(messageProperty.symbol) as Primitive<*>).value as String?
|
||||
private fun getMessageWithName(): String = getMessage()?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
|
||||
fun getCause(): ExceptionState? = getState(causeProperty.symbol)?.let { if (it is ExceptionState) it else null }
|
||||
|
||||
fun getFullDescription(): String {
|
||||
// TODO remainder of the stack trace with "..."
|
||||
val message = getMessage().let { if (it?.isNotEmpty() == true) ": $it" else "" }
|
||||
val message = message.let { if (it?.isNotEmpty() == true) ": $it" else "" }
|
||||
val prefix = if (stackTrace.isNotEmpty()) "\n\t" else ""
|
||||
val postfix = if (stackTrace.size > 10) "\n\t..." else ""
|
||||
val causeMessage = getCause()?.getFullDescription()?.replaceFirst("Exception ", "\nCaused by: ") ?: ""
|
||||
val causeMessage = (cause as? ExceptionState)?.getFullDescription()?.replaceFirst("Exception ", "\nCaused by: ") ?: ""
|
||||
return "Exception $exceptionFqName$message" +
|
||||
stackTrace.subList(0, min(stackTrace.size, 10)).joinToString(separator = "\n\t", prefix = prefix, postfix = postfix) +
|
||||
causeMessage
|
||||
}
|
||||
|
||||
fun getThisAsCauseForException() = ExceptionData(this)
|
||||
override fun toString(): String = message?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
|
||||
companion object {
|
||||
private fun IrClass.getPropertyByName(name: String): IrProperty {
|
||||
|
||||
@@ -45,9 +45,11 @@ internal fun State.asBoolean() = (this as Primitive<*>).value as Boolean
|
||||
internal fun State.asString() = (this as Primitive<*>).value.toString()
|
||||
|
||||
internal fun State.asBooleanOrNull() = (this as? Primitive<*>)?.value as? Boolean
|
||||
internal fun State.asStringOrNull() = (this as Primitive<*>).value as? String
|
||||
|
||||
internal fun State.isSubtypeOf(other: IrType): Boolean {
|
||||
if (this is Primitive<*> && this.value == null) return other.isNullable()
|
||||
if (this is ExceptionState) return this.isSubtypeOf(other.classOrNull!!.owner)
|
||||
|
||||
if (this is Primitive<*> && this.type.isArray() && other.isArray()) {
|
||||
val thisClass = this.typeArguments.single().state.irClass.symbol
|
||||
|
||||
+14
-7
@@ -9,12 +9,13 @@ 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.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
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.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
@@ -22,11 +23,17 @@ import java.lang.invoke.MethodHandle
|
||||
import java.lang.invoke.MethodHandles
|
||||
import java.lang.invoke.MethodType
|
||||
|
||||
internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass, mutableListOf()) {
|
||||
internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
|
||||
override var superWrapperClass: Wrapper? = null
|
||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||
override var outerClass: Variable? = null
|
||||
|
||||
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
||||
private val receiverClass = irClass.defaultType.getClass(true)
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null
|
||||
|
||||
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||
if (irFunction.getEvaluateIntrinsicValue()?.isEmpty() == true) return null // this method will handle IntrinsicEvaluator
|
||||
// if function is actually a getter, then use "get${property.name.capitalize()}" as method name
|
||||
@@ -51,6 +58,10 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex(
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return value.toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val companionObjectValue = mapOf<String, Any>("kotlin.text.Regex\$Companion" to Regex.Companion)
|
||||
|
||||
@@ -184,8 +195,4 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex(
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Wrapper(obj='$typeFqName', value=$value)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ fun generateMap(): String {
|
||||
p.println("package org.jetbrains.kotlin.ir.interpreter.builtins")
|
||||
p.println()
|
||||
p.println("import org.jetbrains.kotlin.ir.interpreter.IrInterpreter")
|
||||
p.println("import org.jetbrains.kotlin.ir.interpreter.state.*")
|
||||
p.println()
|
||||
p.println("/** This file is generated by org.jetbrains.kotlin.backend.common.interpreter.builtins.GenerateBuiltInsMap.generateMap(). DO NOT MODIFY MANUALLY */")
|
||||
p.println()
|
||||
@@ -138,10 +137,7 @@ private fun generateUnaryBody(unaryOperationsMap: Map<CallableDescriptor, Pair<S
|
||||
val methodName = "${function.name}"
|
||||
val parentheses = if (function is FunctionDescriptor) "()" else ""
|
||||
" unaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a -> a.$methodName$parentheses }"
|
||||
} +
|
||||
" unaryOperation<Any?>(\"${irNullCheck.name}\", \"${irNullCheck.valueParameters.first().type.originalKotlinType}\") { a -> a!! },\n" +
|
||||
" unaryOperation<ExceptionState>(\"message\", \"Throwable\") { a -> a.getMessage() },\n" +
|
||||
" unaryOperation<ExceptionState>(\"cause\", \"Throwable\") { a -> a.getCause() }"
|
||||
} + " unaryOperation<Any?>(\"${irNullCheck.name}\", \"${irNullCheck.valueParameters.first().type.originalKotlinType}\") { a -> a!! }"
|
||||
}
|
||||
|
||||
private fun generateBinaryBody(
|
||||
|
||||
Reference in New Issue
Block a user