Move additional stack filling in ExceptionState class

This commit is contained in:
Ivan Kylchik
2020-03-27 15:31:49 +03:00
parent 900e78b39b
commit ad7055b8a0
2 changed files with 32 additions and 29 deletions
@@ -123,7 +123,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
else -> TODO("${this.javaClass} not supported") else -> TODO("${this.javaClass} not supported")
} }
return when (code) { return when (code) { // TODO move to label class
Code.RETURN -> when (this) { Code.RETURN -> when (this) {
is IrCall -> if (code.info == this.symbol.descriptor.toString()) Code.NEXT else code is IrCall -> if (code.info == this.symbol.descriptor.toString()) Code.NEXT else code
is IrReturnableBlock -> if (code.info == this.symbol.descriptor.toString()) Code.NEXT else code is IrReturnableBlock -> if (code.info == this.symbol.descriptor.toString()) Code.NEXT else code
@@ -150,36 +150,12 @@ class IrInterpreter(irModule: IrModuleFragment) {
val exceptionName = e::class.java.simpleName val exceptionName = e::class.java.simpleName
val irExceptionClass = irExceptions.firstOrNull { it.name.asString() == exceptionName } ?: irBuiltIns.throwableClass.owner val irExceptionClass = irExceptions.firstOrNull { it.name.asString() == exceptionName } ?: irBuiltIns.throwableClass.owner
// TODO do we really need this?... It will point to JVM stdlib
val additionalStack = mutableListOf<String>()
if (e.stackTrace.any { it.className == "java.lang.invoke.MethodHandle" }) {
for ((index, stackTraceElement) in e.stackTrace.withIndex()) {
if (stackTraceElement.methodName == "invokeWithArguments") {
additionalStack.addAll(e.stackTrace.slice(0 until index).reversed().map { "at $it" })
break
}
}
var cause = e.cause
val lastNeededValue = e.stackTrace.first().className + "." + e.stackTrace.first().methodName
while (cause != null) {
for ((causeStackIndex, causeStackTraceElement) in cause.stackTrace.withIndex()) {
val currentStackTraceValue = causeStackTraceElement.className + "." + causeStackTraceElement.methodName
if (currentStackTraceValue == lastNeededValue) {
cause.stackTrace = cause.stackTrace.sliceArray(0 until causeStackIndex).reversedArray()
break
}
}
cause = cause.cause
}
}
val exceptionState = when { val exceptionState = when {
// this block is used to replace jvm null pointer exception with common one // this block is used to replace jvm null pointer exception with common one
// TODO figure something better // TODO figure something better
irExceptionClass == irBuiltIns.throwableClass.owner && exceptionName == "KotlinNullPointerException" -> irExceptionClass == irBuiltIns.throwableClass.owner && exceptionName == "KotlinNullPointerException" ->
ExceptionState(e, irExceptions.first { it.name.asString() == "NullPointerException" }, stackTrace + additionalStack) ExceptionState(e, irExceptions.first { it.name.asString() == "NullPointerException" }, stackTrace)
else -> ExceptionState(e, irExceptionClass, stackTrace + additionalStack) else -> ExceptionState(e, irExceptionClass, stackTrace)
} }
data.pushReturnValue(exceptionState) data.pushReturnValue(exceptionState)
@@ -322,7 +322,7 @@ class ExceptionState private constructor(
init { init {
instance = this instance = this
this.stackTrace = stackTrace.reversed() this.stackTrace = stackTrace.reversed()
if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClass.fqNameForIrSerialization.asString() if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName()
if (fields.none { it.descriptor.equalTo(messageProperty.descriptor) }) { if (fields.none { it.descriptor.equalTo(messageProperty.descriptor) }) {
setMessage() setMessage()
@@ -341,7 +341,7 @@ class ExceptionState private constructor(
constructor( constructor(
exception: Throwable, irClass: IrClass, stackTrace: List<String> exception: Throwable, irClass: IrClass, stackTrace: List<String>
) : this(irClass, evaluateFields(exception, irClass, stackTrace), stackTrace) { ) : this(irClass, evaluateFields(exception, irClass, stackTrace), stackTrace + evaluateAdditionalStackTrace(exception)) {
if (irClass.name.asString() != exception::class.java.simpleName) { 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 // ir class wasn't found in classpath, a stub was passed => need to save java class hierarchy
this.exceptionFqName = exception::class.java.name this.exceptionFqName = exception::class.java.name
@@ -414,6 +414,33 @@ class ExceptionState private constructor(
} }
return listOfNotNull(messageVar, causeVar).toMutableList() return listOfNotNull(messageVar, causeVar).toMutableList()
} }
private fun evaluateAdditionalStackTrace(e: Throwable): List<String> {
// TODO do we really need this?... It will point to JVM stdlib
val additionalStack = mutableListOf<String>()
if (e.stackTrace.any { it.className == "java.lang.invoke.MethodHandle" }) {
for ((index, stackTraceElement) in e.stackTrace.withIndex()) {
if (stackTraceElement.methodName == "invokeWithArguments") {
additionalStack.addAll(e.stackTrace.slice(0 until index).reversed().map { "at $it" })
break
}
}
var cause = e.cause
val lastNeededValue = e.stackTrace.first().let { it.className + "." + it.methodName }
while (cause != null) {
for ((causeStackIndex, causeStackTraceElement) in cause.stackTrace.withIndex()) {
val currentStackTraceValue = causeStackTraceElement.let { it.className + "." + it.methodName }
if (currentStackTraceValue == lastNeededValue) {
cause.stackTrace = cause.stackTrace.sliceArray(0 until causeStackIndex).reversedArray()
break
}
}
cause = cause.cause
}
}
return additionalStack
}
} }
} }