Debugger: Support synchronized blocks and functions in evaluator (KT-11888)

This commit is contained in:
Yan Zhulanow
2019-04-16 20:15:20 +03:00
parent 55bbcc4601
commit ee0daae2ab
5 changed files with 49 additions and 0 deletions
@@ -20,6 +20,7 @@ import com.sun.jdi.ArrayReference
import com.sun.jdi.ArrayType
import com.sun.jdi.ClassLoaderReference
import com.sun.jdi.Value
import jdk.internal.org.objectweb.asm.Opcodes
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.Label
@@ -63,6 +64,7 @@ interface ClassLoadingAdapter {
private fun analyzeClass(classToLoad: ClassToLoad, info: ClassInfoForEvaluator): ClassInfoForEvaluator {
val classNode = ClassNode().apply { ClassReader(classToLoad.bytes).accept(this, 0) }
val methodToRun = classNode.methods.single { it.name == GENERATED_FUNCTION_NAME }
val visitedLabels = hashSetOf<Label>()
@@ -78,6 +80,11 @@ interface ClassLoadingAdapter {
is TableSwitchInsnNode, is LookupSwitchInsnNode -> {
return info.copy(containsCodeUnsupportedInEval4J = true)
}
is InsnNode -> {
if (insn.opcode == Opcodes.MONITORENTER || insn.opcode == Opcodes.MONITOREXIT) {
return info.copy(containsCodeUnsupportedInEval4J = true)
}
}
}
val nextInsn = insn.next ?: return info
@@ -0,0 +1,9 @@
package synchronizedBlock
fun main() {
//Breakpoint!
val a = 5
}
// EXPRESSION: synchronized(Any()) { "foo" }
// RESULT: "foo": Ljava/lang/String;
@@ -0,0 +1,10 @@
class Foo {
@Synchronized
fun foo(): Int {
return 5
}
}
Foo().foo()
// RESULT: 5: I
@@ -0,0 +1,18 @@
LineBreakpoint created at synchronizedBlock.kt:5
Run Java
Connected to the target VM
synchronizedBlock.kt:5
Compile bytecode for synchronized(Any()) { "foo" }
Compile bytecode for class Foo {
@Synchronized
fun foo(): Int {
return 5
}
}
Foo().foo()
// RESULT: 5: I
Disconnected from the target VM
Process finished with exit code 0
@@ -391,6 +391,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt");
}
@TestMetadata("synchronizedBlock.kt")
public void testSynchronizedBlock() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/synchronizedBlock.kt");
}
@TestMetadata("typeParameterRef.kt")
public void testTypeParameterRef() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/typeParameterRef.kt");