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