(CoroutineDebugger) kotlinx.coroutines.core:1.3.5 support / dynamicProxy(interface) classes
This commit is contained in:
+3
-3
@@ -17,12 +17,12 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
|||||||
class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecutionContext) :
|
class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecutionContext) :
|
||||||
CoroutineInfoProvider {
|
CoroutineInfoProvider {
|
||||||
val log by logger
|
val log by logger
|
||||||
private val debugProbesImpl = DebugProbesImpl(executionContext)
|
private val debugProbesImpl = DebugProbesImpl.instance(executionContext)
|
||||||
private val locationCache = LocationCache(executionContext)
|
private val locationCache = LocationCache(executionContext)
|
||||||
private val debugMetadata: DebugMetadata? = DebugMetadata.instance(executionContext)
|
private val debugMetadata: DebugMetadata? = DebugMetadata.instance(executionContext)
|
||||||
|
|
||||||
override fun dumpCoroutinesInfo(): List<CoroutineInfoData> {
|
override fun dumpCoroutinesInfo(): List<CoroutineInfoData> {
|
||||||
val result = debugProbesImpl.dumpCoroutinesInfo(executionContext)
|
val result = debugProbesImpl?.dumpCoroutinesInfo(executionContext) ?: emptyList()
|
||||||
return result.mapNotNull { mapToCoroutineInfoData(it) }
|
return result.mapNotNull { mapToCoroutineInfoData(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution
|
|||||||
|
|
||||||
fun isInstalled(): Boolean {
|
fun isInstalled(): Boolean {
|
||||||
try {
|
try {
|
||||||
return debugProbesImpl.isInstalledValue ?: false
|
return debugProbesImpl?.isInstalledValue ?: false
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
log.error("Exception happened while checking agent status.", e)
|
log.error("Exception happened while checking agent status.", e)
|
||||||
return false
|
return false
|
||||||
|
|||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.debugger.coroutine.proxy.mirror
|
||||||
|
|
||||||
|
import com.sun.jdi.*
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
||||||
|
|
||||||
|
abstract class BaseDynamicMirror<T>(val value: ObjectReference, val name: String, val context: DefaultExecutionContext) {
|
||||||
|
val log by logger
|
||||||
|
|
||||||
|
val cls: ReferenceType? = value.referenceType()
|
||||||
|
|
||||||
|
fun makeField(fieldName: String): Field? =
|
||||||
|
cls?.let { it.fieldByName(fieldName) }
|
||||||
|
|
||||||
|
fun makeMethod(methodName: String): Method? =
|
||||||
|
cls?.let { it.methodsByName(methodName).single() }
|
||||||
|
|
||||||
|
fun makeMethod(methodName: String, signature: String): Method? =
|
||||||
|
cls?.let { it.methodsByName(methodName, signature).single() }
|
||||||
|
|
||||||
|
fun isCompatible(value: ObjectReference?) =
|
||||||
|
value?.let { it.referenceType().isSubTypeOrSame(name) } ?: false
|
||||||
|
|
||||||
|
fun mirror(): T? {
|
||||||
|
if (!isCompatible(value)) {
|
||||||
|
log.trace("Value ${value.referenceType()} is not compatible with $name.")
|
||||||
|
return null
|
||||||
|
} else
|
||||||
|
return fetchMirror(value, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun staticObjectValue(fieldName: String): ObjectReference? {
|
||||||
|
val keyFieldRef = makeField(fieldName)
|
||||||
|
return cls?.let { it.getValue(keyFieldRef) as? ObjectReference }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun staticMethodValue(instance: ObjectReference?, method: Method?, context: DefaultExecutionContext, vararg values: Value?) =
|
||||||
|
instance?.let {
|
||||||
|
method?.let { m ->
|
||||||
|
context.invokeMethod(it, m, values.asList()) as? ObjectReference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun staticMethodValue(method: Method?, context: DefaultExecutionContext, vararg values: Value?) =
|
||||||
|
cls?.let {
|
||||||
|
method?.let {
|
||||||
|
if (cls is ClassType)
|
||||||
|
context.invokeMethodSafe(cls, method, values.asList()) as? ObjectReference
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringValue(value: ObjectReference, field: Field?) =
|
||||||
|
field?.let {
|
||||||
|
(value.getValue(it) as? StringReference)?.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byteValue(value: ObjectReference, field: Field?) =
|
||||||
|
field?.let {
|
||||||
|
(value.getValue(it) as? ByteValue)?.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun threadValue(value: ObjectReference, field: Field?) =
|
||||||
|
field?.let {
|
||||||
|
value.getValue(it) as? ThreadReference
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringValue(value: ObjectReference, method: Method?, context: DefaultExecutionContext) =
|
||||||
|
method?.let {
|
||||||
|
(context.invokeMethod(value, it, emptyList()) as? StringReference)?.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun objectValue(value: ObjectReference?, method: Method?, context: DefaultExecutionContext, vararg values: Value) =
|
||||||
|
value?.let {
|
||||||
|
method?.let {
|
||||||
|
context.invokeMethodAsObject(value, method, *values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun longValue(value: ObjectReference, method: Method?, context: DefaultExecutionContext, vararg values: Value) =
|
||||||
|
method?.let { (context.invokeMethod(value, it, values.asList()) as? LongValue)?.longValue() }
|
||||||
|
|
||||||
|
fun intValue(value: ObjectReference, method: Method?, context: DefaultExecutionContext, vararg values: Value) =
|
||||||
|
method?.let { (context.invokeMethod(value, it, values.asList()) as? IntegerValue)?.intValue() }
|
||||||
|
|
||||||
|
fun booleanValue(value: ObjectReference?, method: Method?, context: DefaultExecutionContext, vararg values: Value): Boolean? {
|
||||||
|
value ?: return null
|
||||||
|
method ?: return null
|
||||||
|
return (context.invokeMethod(value, method, values.asList()) as? BooleanValue)?.booleanValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun objectValue(value: ObjectReference, field: Field?) =
|
||||||
|
field?.let { value.getValue(it) as ObjectReference? }
|
||||||
|
|
||||||
|
fun intValue(value: ObjectReference, field: Field?) =
|
||||||
|
field?.let { (value.getValue(it) as? IntegerValue)?.intValue() }
|
||||||
|
|
||||||
|
fun longValue(value: ObjectReference, field: Field?) =
|
||||||
|
field?.let { (value.getValue(it) as? LongValue)?.longValue() }
|
||||||
|
|
||||||
|
fun booleanValue(value: ObjectReference?, field: Field?) =
|
||||||
|
field?.let { (value?.getValue(field) as? BooleanValue)?.booleanValue() }
|
||||||
|
|
||||||
|
protected abstract fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): T?
|
||||||
|
}
|
||||||
+2
-2
@@ -67,8 +67,8 @@ class CoroutineId(context: DefaultExecutionContext) : ContextKey<Long>("kotlinx.
|
|||||||
override fun key() = key
|
override fun key() = key
|
||||||
}
|
}
|
||||||
|
|
||||||
class Job(context: DefaultExecutionContext) : ContextKey<ObjectReference>("kotlinx.coroutines.Job", context) {
|
class Job(context: DefaultExecutionContext) : ContextKey<ObjectReference>("kotlinx.coroutines.Job\$Key", context) {
|
||||||
val key = staticObjectValue("Key")
|
val key = staticObjectValue("\$\$INSTANCE")
|
||||||
|
|
||||||
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): ObjectReference? {
|
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): ObjectReference? {
|
||||||
return value
|
return value
|
||||||
|
|||||||
+35
-10
@@ -7,16 +7,18 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror
|
|||||||
|
|
||||||
import com.sun.jdi.*
|
import com.sun.jdi.*
|
||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
||||||
|
|
||||||
class DebugProbesImpl internal constructor(context: DefaultExecutionContext) :
|
class DebugProbesImpl private constructor(context: DefaultExecutionContext) :
|
||||||
BaseMirror<MirrorOfDebugProbesImpl>("kotlinx.coroutines.debug.internal.DebugProbesImpl", context) {
|
BaseMirror<MirrorOfDebugProbesImpl>("kotlinx.coroutines.debug.internal.DebugProbesImpl", context) {
|
||||||
val javaLangListMirror = JavaUtilAbstractCollection(context)
|
val javaLangListMirror = JavaUtilAbstractCollection(context)
|
||||||
val stackTraceElement = StackTraceElement(context)
|
val stackTraceElement = StackTraceElement(context)
|
||||||
val coroutineInfo = CoroutineInfo(this, context)
|
val coroutineInfo = CoroutineInfo.instance(this, context) ?: throw IllegalStateException("CoroutineInfo implementation not found.")
|
||||||
val debugProbesCoroutineOwner = DebugProbesImpl_CoroutineOwner(coroutineInfo, context)
|
val debugProbesCoroutineOwner = DebugProbesImpl_CoroutineOwner(coroutineInfo, context)
|
||||||
val instance = staticObjectValue("INSTANCE")
|
val instance = staticObjectValue("INSTANCE")
|
||||||
val isInstalledMethod = makeMethod("isInstalled\$kotlinx_coroutines_debug", "()Z")
|
val isInstalledMethod = makeMethod("isInstalled\$kotlinx_coroutines_debug", "()Z")
|
||||||
|
?: makeMethod("isInstalled\$kotlinx_coroutines_core", "()Z") ?: throw IllegalStateException("isInstalledMethod not found")
|
||||||
val isInstalledValue = booleanValue(instance, isInstalledMethod, context)
|
val isInstalledValue = booleanValue(instance, isInstalledMethod, context)
|
||||||
val enhanceStackTraceWithThreadDumpMethod = makeMethod("enhanceStackTraceWithThreadDump")
|
val enhanceStackTraceWithThreadDumpMethod = makeMethod("enhanceStackTraceWithThreadDump")
|
||||||
val dumpMethod = makeMethod("dumpCoroutinesInfo", "()Ljava/util/List;")
|
val dumpMethod = makeMethod("dumpCoroutinesInfo", "()Ljava/util/List;")
|
||||||
@@ -49,10 +51,13 @@ class DebugProbesImpl internal constructor(context: DefaultExecutionContext) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val log by logger
|
||||||
|
|
||||||
fun instance(context: DefaultExecutionContext) =
|
fun instance(context: DefaultExecutionContext) =
|
||||||
try {
|
try {
|
||||||
DebugProbesImpl(context)
|
DebugProbesImpl(context)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
|
log.warn("Attempt to access DebugProbesImpl", e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,12 +84,15 @@ data class MirrorOfCoroutineOwner(val that: ObjectReference, val coroutineInfo:
|
|||||||
|
|
||||||
data class MirrorOfDebugProbesImpl(val that: ObjectReference, val instance: ObjectReference?, val isInstalled: Boolean?)
|
data class MirrorOfDebugProbesImpl(val that: ObjectReference, val instance: ObjectReference?, val isInstalled: Boolean?)
|
||||||
|
|
||||||
class CoroutineInfo(val debugProbesImplMirror: DebugProbesImpl, context: DefaultExecutionContext) :
|
class CoroutineInfo private constructor(
|
||||||
BaseMirror<MirrorOfCoroutineInfo>("kotlinx.coroutines.debug.CoroutineInfo", context) {
|
val debugProbesImplMirror: DebugProbesImpl,
|
||||||
|
context: DefaultExecutionContext,
|
||||||
|
val className: String = AGENT_134_CLASS_NAME
|
||||||
|
) :
|
||||||
|
BaseMirror<MirrorOfCoroutineInfo>(className, context) {
|
||||||
val javaLangMirror = JavaLangMirror(context)
|
val javaLangMirror = JavaLangMirror(context)
|
||||||
val javaLangListMirror = JavaUtilAbstractCollection(context)
|
val javaLangListMirror = JavaUtilAbstractCollection(context)
|
||||||
private val coroutineContextMirror = CoroutineContext(context)
|
private val coroutineContextMirror = CoroutineContext(context)
|
||||||
private val coroutineStackFrameMirror = CoroutineStackFrame(context)
|
|
||||||
private val stackTraceElement = StackTraceElement(context)
|
private val stackTraceElement = StackTraceElement(context)
|
||||||
private val contextFieldRef = makeField("context")
|
private val contextFieldRef = makeField("context")
|
||||||
private val creationStackBottom = makeField("creationStackBottom")
|
private val creationStackBottom = makeField("creationStackBottom")
|
||||||
@@ -96,13 +104,30 @@ class CoroutineInfo(val debugProbesImplMirror: DebugProbesImpl, context: Default
|
|||||||
private val lastObservedFrameField = makeField("lastObservedFrame")
|
private val lastObservedFrameField = makeField("lastObservedFrame")
|
||||||
private val lastObservedThreadField = makeField("lastObservedThread")
|
private val lastObservedThreadField = makeField("lastObservedThread")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val log by logger
|
||||||
|
const val AGENT_134_CLASS_NAME = "kotlinx.coroutines.debug.CoroutineInfo"
|
||||||
|
const val AGENT_135_AND_UP_CLASS_NAME = "kotlinx.coroutines.debug.internal.DebugCoroutineInfo"
|
||||||
|
|
||||||
|
fun instance(debugProbesImplMirror: DebugProbesImpl, context: DefaultExecutionContext): CoroutineInfo? {
|
||||||
|
val classType = context.findClassSafe(AGENT_134_CLASS_NAME) ?: context.findClassSafe(AGENT_135_AND_UP_CLASS_NAME) ?: return null
|
||||||
|
try {
|
||||||
|
return CoroutineInfo(debugProbesImplMirror, context, classType.name())
|
||||||
|
} catch (e: IllegalStateException) {
|
||||||
|
log.warn("coroutine-debugger: $classType not found", e)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCoroutineInfo {
|
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCoroutineInfo {
|
||||||
val state = objectValue(value, stateMethod, context)?.let {
|
val state = objectValue(value, stateMethod, context)?.let {
|
||||||
stringValue(it, javaLangMirror.toString, context)
|
stringValue(it, javaLangMirror.toString, context)
|
||||||
}
|
}
|
||||||
val coroutineContext = coroutineContextMirror.mirror(objectValue(value, contextFieldRef), context)
|
val coroutineContext = coroutineContextMirror.mirror(objectValue(value, contextFieldRef), context)
|
||||||
val creationStackBottomObjectReference = objectValue(value, creationStackBottom)
|
val creationStackBottomObjectReference = objectValue(value, creationStackBottom)
|
||||||
val creationStackBottom = coroutineStackFrameMirror.mirror(creationStackBottomObjectReference, context)
|
val creationStackBottom =
|
||||||
|
creationStackBottomObjectReference?.let { CoroutineStackFrame(creationStackBottomObjectReference, context).mirror() }
|
||||||
val sequenceNumber = longValue(value, sequenceNumberField)
|
val sequenceNumber = longValue(value, sequenceNumberField)
|
||||||
val creationStackTraceList = objectValue(value, creationStackTraceMethod, context)
|
val creationStackTraceList = objectValue(value, creationStackTraceMethod, context)
|
||||||
val creationStackTraceMirror = javaLangListMirror.mirror(creationStackTraceList, context)
|
val creationStackTraceMirror = javaLangListMirror.mirror(creationStackTraceList, context)
|
||||||
@@ -127,9 +152,9 @@ class CoroutineInfo(val debugProbesImplMirror: DebugProbesImpl, context: Default
|
|||||||
lastObservedFrame
|
lastObservedFrame
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class MirrorOfCoroutineInfo(
|
data class MirrorOfCoroutineInfo(
|
||||||
val that: ObjectReference,
|
val that: ObjectReference,
|
||||||
val context: MirrorOfCoroutineContext?,
|
val context: MirrorOfCoroutineContext?,
|
||||||
@@ -142,8 +167,8 @@ data class MirrorOfCoroutineInfo(
|
|||||||
val lastObservedFrame: ObjectReference?
|
val lastObservedFrame: ObjectReference?
|
||||||
)
|
)
|
||||||
|
|
||||||
class CoroutineStackFrame(context: DefaultExecutionContext) :
|
class CoroutineStackFrame(value: ObjectReference, context: DefaultExecutionContext) :
|
||||||
BaseMirror<MirrorOfCoroutineStackFrame>("kotlin.coroutines.jvm.internal.CoroutineStackFrame", context) {
|
BaseDynamicMirror<MirrorOfCoroutineStackFrame>(value, "kotlin.coroutines.jvm.internal.CoroutineStackFrame", context) {
|
||||||
private val stackTraceElementMirror = StackTraceElement(context)
|
private val stackTraceElementMirror = StackTraceElement(context)
|
||||||
private val callerFrameMethod = makeMethod("getCallerFrame")
|
private val callerFrameMethod = makeMethod("getCallerFrame")
|
||||||
private val getStackTraceElementMethod = makeMethod("getStackTraceElement")
|
private val getStackTraceElementMethod = makeMethod("getStackTraceElement")
|
||||||
@@ -151,7 +176,7 @@ class CoroutineStackFrame(context: DefaultExecutionContext) :
|
|||||||
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCoroutineStackFrame? {
|
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCoroutineStackFrame? {
|
||||||
val objectReference = objectValue(value, callerFrameMethod, context)
|
val objectReference = objectValue(value, callerFrameMethod, context)
|
||||||
val callerFrame = if (objectReference is ObjectReference)
|
val callerFrame = if (objectReference is ObjectReference)
|
||||||
this.mirror(objectReference, context) else null
|
CoroutineStackFrame(objectReference, context).mirror() else null
|
||||||
val stackTraceElementReference = objectValue(value, getStackTraceElementMethod, context)
|
val stackTraceElementReference = objectValue(value, getStackTraceElementMethod, context)
|
||||||
val stackTraceElement =
|
val stackTraceElement =
|
||||||
if (stackTraceElementReference is ObjectReference) stackTraceElementMirror.mirror(stackTraceElementReference, context) else null
|
if (stackTraceElementReference is ObjectReference) stackTraceElementMirror.mirror(stackTraceElementReference, context) else null
|
||||||
|
|||||||
+4
-4
@@ -9,20 +9,20 @@ import com.sun.jdi.*
|
|||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame
|
||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
||||||
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
abstract class BaseMirror<T>(val name: String, context: DefaultExecutionContext) {
|
abstract class BaseMirror<T>(val name: String, context: DefaultExecutionContext) {
|
||||||
val log by logger
|
val log by logger
|
||||||
protected val cls = context.findClassSafe(name)
|
protected val cls = context.findClassSafe(name) ?: throw IllegalStateException("coroutine-debugger: class $name not found.")
|
||||||
|
|
||||||
fun makeField(fieldName: String): Field? =
|
fun makeField(fieldName: String): Field? =
|
||||||
cls?.let { it.fieldByName(fieldName) }
|
cls?.let { it.fieldByName(fieldName) }
|
||||||
|
|
||||||
fun makeMethod(methodName: String): Method? =
|
fun makeMethod(methodName: String): Method? =
|
||||||
cls?.let { it.methodsByName(methodName).single() }
|
cls?.let { it.methodsByName(methodName).singleOrNull() }
|
||||||
|
|
||||||
fun makeMethod(methodName: String, signature: String): Method? =
|
fun makeMethod(methodName: String, signature: String): Method? =
|
||||||
cls?.let { it.methodsByName(methodName, signature).single() }
|
cls?.let { it.methodsByName(methodName, signature).singleOrNull() }
|
||||||
|
|
||||||
fun isCompatible(value: ObjectReference?) =
|
fun isCompatible(value: ObjectReference?) =
|
||||||
value?.let { it.referenceType().isSubTypeOrSame(name) } ?: false
|
value?.let { it.referenceType().isSubTypeOrSame(name) } ?: false
|
||||||
|
|||||||
+5
-1
@@ -10,9 +10,10 @@ import com.sun.jdi.ClassType
|
|||||||
import com.sun.jdi.ObjectReference
|
import com.sun.jdi.ObjectReference
|
||||||
import com.sun.jdi.StringReference
|
import com.sun.jdi.StringReference
|
||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isBaseContinuationImpl
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isBaseContinuationImpl
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
|
||||||
|
|
||||||
class DebugMetadata internal constructor(context: DefaultExecutionContext) :
|
class DebugMetadata private constructor(context: DefaultExecutionContext) :
|
||||||
BaseMirror<MirrorOfDebugProbesImpl>("kotlin.coroutines.jvm.internal.DebugMetadataKt", context) {
|
BaseMirror<MirrorOfDebugProbesImpl>("kotlin.coroutines.jvm.internal.DebugMetadataKt", context) {
|
||||||
private val getStackTraceElementMethod = makeMethod("getStackTraceElement")
|
private val getStackTraceElementMethod = makeMethod("getStackTraceElement")
|
||||||
private val getSpilledVariableFieldMappingMethod =
|
private val getSpilledVariableFieldMappingMethod =
|
||||||
@@ -42,10 +43,13 @@ class DebugMetadata internal constructor(context: DefaultExecutionContext) :
|
|||||||
staticMethodValue(getSpilledVariableFieldMappingMethod, context, value) as? ArrayReference
|
staticMethodValue(getSpilledVariableFieldMappingMethod, context, value) as? ArrayReference
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val log by logger
|
||||||
|
|
||||||
fun instance(context: DefaultExecutionContext) =
|
fun instance(context: DefaultExecutionContext) =
|
||||||
try {
|
try {
|
||||||
DebugMetadata(context)
|
DebugMetadata(context)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
|
log.warn("Attempt to access DebugMetadata", e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user