From bbdeb3efacaba54bdab36ec3d87a714e39a4288e Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Wed, 13 Mar 2019 20:22:45 +0300 Subject: [PATCH] Avoid using 'loadClass()' as it doesn't cache the results --- .../debugger/evaluate/ExecutionContext.kt | 47 ++++++++++--------- .../evaluate/KotlinEvaluationBuilder.kt | 6 +-- .../AbstractAndroidClassLoadingAdapter.kt | 2 +- .../variables/EvaluatorValueConverter.kt | 6 +-- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt index ace91128273..c80312d27d0 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt @@ -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) { diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt index cbd7ad0b933..3748869360b 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -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) diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AbstractAndroidClassLoadingAdapter.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AbstractAndroidClassLoadingAdapter.kt index ece5774fc3e..7554ef21f0d 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AbstractAndroidClassLoadingAdapter.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/AbstractAndroidClassLoadingAdapter.kt @@ -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 } diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/variables/EvaluatorValueConverter.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/variables/EvaluatorValueConverter.kt index f3bf2a587df..01dc668ec04 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/variables/EvaluatorValueConverter.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/variables/EvaluatorValueConverter.kt @@ -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)