Avoid using 'loadClass()' as it doesn't cache the results

This commit is contained in:
Yan Zhulanow
2019-03-13 20:22:45 +03:00
parent e79ee1ba8e
commit bbdeb3efac
4 changed files with 33 additions and 28 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.debugger.evaluate
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.evaluation.EvaluateException
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.impl.DebuggerUtilsEx
import com.intellij.debugger.jdi.StackFrameProxyImpl
@@ -53,31 +54,35 @@ class ExecutionContext(val evaluationContext: EvaluationContextImpl, val framePr
return debugProcess.newInstance(arrayType, dimension)
}
@Throws(
InvocationException::class,
ClassNotLoadedException::class,
IncompatibleThreadStateException::class,
InvalidTypeException::class,
EvaluateException::class
)
fun loadClass(asmType: Type, classLoader: ClassLoaderReference? = null): ReferenceType? {
return loadClass(asmType.className, classLoader)
}
@Throws(EvaluateException::class)
fun findClass(name: String, classLoader: ClassLoaderReference? = null): ReferenceType? {
debugProcess.findClass(evaluationContext, name, classLoader)?.let { return it }
@Throws(
InvocationException::class,
ClassNotLoadedException::class,
IncompatibleThreadStateException::class,
InvalidTypeException::class,
EvaluateException::class
)
fun loadClass(name: String, classLoader: ClassLoaderReference? = null): ReferenceType? {
return debugProcess.loadClass(evaluationContext, name, classLoader)
// If 'isAutoLoadClasses' is true, `findClass()` already did this
if (!evaluationContext.isAutoLoadClasses) {
try {
debugProcess.loadClass(evaluationContext, name, classLoader)
} catch (e: InvocationException) {
throw EvaluateExceptionUtil.createEvaluateException(e)
} catch (e: ClassNotLoadedException) {
throw EvaluateExceptionUtil.createEvaluateException(e)
} catch (e: IncompatibleThreadStateException) {
throw EvaluateExceptionUtil.createEvaluateException(e)
} catch (e: InvalidTypeException) {
throw EvaluateExceptionUtil.createEvaluateException(e)
}
}
return null
}
@Throws(EvaluateException::class)
fun findClass(name: String, classLoader: ClassLoaderReference? = null): ReferenceType? {
return debugProcess.findClass(evaluationContext, name, classLoader)
fun findClass(asmType: Type, classLoader: ClassLoaderReference? = null): ReferenceType? {
if (asmType.sort != Type.OBJECT && asmType.sort != Type.ARRAY) {
return null
}
return findClass(asmType.className, classLoader)
}
fun keepReference(reference: ObjectReference) {
@@ -292,7 +292,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
): Value? {
return try {
runEvaluation(context, compiledData, classLoader) { args ->
val mainClassType = context.loadClass(Type.getObjectType(GENERATED_CLASS_NAME), classLoader) as? ClassType
val mainClassType = context.findClass(GENERATED_CLASS_NAME, classLoader) as? ClassType
?: error("Can not find class \"$GENERATED_CLASS_NAME\"")
val mainMethod = mainClassType.methods().single { it.name() == GENERATED_FUNCTION_NAME }
val returnValue = context.invokeMethod(mainClassType, mainMethod, args)
@@ -332,11 +332,11 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
// Preload additional classes
compiledData.classes
.filter { !it.isMainClass }
.forEach { context.loadClass(Type.getObjectType(it.className), classLoader) }
.forEach { context.findClass(it.className, classLoader) }
return context.vm.virtualMachine.executeWithBreakpointsDisabled {
for (parameterType in compiledData.mainMethodSignature.parameterTypes) {
context.loadClass(parameterType, classLoader)
context.findClass(parameterType, classLoader)
}
val args = calculateMainMethodCallArguments(context, compiledData)
block(args)
@@ -35,7 +35,7 @@ abstract class AbstractAndroidClassLoadingAdapter : ClassLoadingAdapter {
protected fun tryLoadClass(context: ExecutionContext, fqName: String, classLoader: ClassLoaderReference?): ReferenceType? {
return try {
context.loadClass(fqName, classLoader)
context.debugProcess.loadClass(context.evaluationContext, fqName, classLoader)
} catch (e: Throwable) {
null
}
@@ -130,7 +130,7 @@ class EvaluatorValueConverter(private val context: ExecutionContext) {
val unboxedType = value.asmType()
val boxedType = box(unboxedType)
val boxedTypeClass = (context.loadClass(boxedType) as ClassType?)
val boxedTypeClass = (context.findClass(boxedType) as ClassType?)
?: error("Class $boxedType is not loaded")
val methodDesc = AsmType.getMethodDescriptor(boxedType, unboxedType)
@@ -173,13 +173,13 @@ class EvaluatorValueConverter(private val context: ExecutionContext) {
val primitiveType = value.asmType()
val refType = PRIMITIVE_TO_REF.getValue(primitiveType)
val refTypeClass = (context.loadClass(refType) as ClassType?)
val refTypeClass = (context.findClass(refType) as ClassType?)
?: error("Class $refType is not loaded")
return wrapRef(value, refTypeClass)
} else {
val refType = AsmType.getType(Ref.ObjectRef::class.java)
val refTypeClass = (context.loadClass(refType) as ClassType?)
val refTypeClass = (context.findClass(refType) as ClassType?)
?: error("Class $refType is not loaded")
return wrapRef(value, refTypeClass)