Evaluate expression: support EE for shared vars
This commit is contained in:
@@ -933,7 +933,8 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type sharedTypeForType(Type type) {
|
@NotNull
|
||||||
|
public static Type sharedTypeForType(@NotNull Type type) {
|
||||||
switch (type.getSort()) {
|
switch (type.getSort()) {
|
||||||
case Type.OBJECT:
|
case Type.OBJECT:
|
||||||
case Type.ARRAY:
|
case Type.ARRAY:
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ import org.jetbrains.jet.plugin.caches.resolve.JavaResolveExtension
|
|||||||
import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl
|
import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.jet.codegen.StackValue
|
||||||
|
|
||||||
private val RECEIVER_NAME = "\$receiver"
|
private val RECEIVER_NAME = "\$receiver"
|
||||||
private val THIS_NAME = "this"
|
private val THIS_NAME = "this"
|
||||||
@@ -339,18 +340,12 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
|
|||||||
if (this0 != null) return this0
|
if (this0 != null) return this0
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val localVariable = frame.visibleVariableByName(name)
|
|
||||||
if (localVariable != null) {
|
|
||||||
val eval4jValue = frame.getValue(localVariable).asValue()
|
|
||||||
if (isValueOfCorrectType(eval4jValue, asmType, checkType)) return eval4jValue
|
|
||||||
}
|
|
||||||
|
|
||||||
val eval4j = JDIEval(frame.virtualMachine()!!,
|
val eval4j = JDIEval(frame.virtualMachine()!!,
|
||||||
getClassLoader()!!,
|
getClassLoader()!!,
|
||||||
getSuspendContext().getThread()?.getThreadReference()!!,
|
getSuspendContext().getThread()?.getThreadReference()!!,
|
||||||
getSuspendContext().getInvokePolicy())
|
getSuspendContext().getInvokePolicy())
|
||||||
|
|
||||||
fun JDIEval.getField(owner: Value, name: String, asmType: Type?): Value? {
|
fun JDIEval.getField(owner: Value, name: String, asmType: Type?, checkType: Boolean): Value? {
|
||||||
val fieldDescription = FieldDescription(owner.asmType.getInternalName(), name, asmType?.getDescriptor() ?: "", isStatic = false)
|
val fieldDescription = FieldDescription(owner.asmType.getInternalName(), name, asmType?.getDescriptor() ?: "", isStatic = false)
|
||||||
try {
|
try {
|
||||||
val fieldValue = getField(owner, fieldDescription)
|
val fieldValue = getField(owner, fieldDescription)
|
||||||
@@ -362,14 +357,39 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Value.isSharedVar(expectedType: Type?): Boolean {
|
||||||
|
return expectedType != null && this.asmType == StackValue.sharedTypeForType(expectedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JDIEval.getValueForSharedVar(value: Value, expectedType: Type?, checkType: Boolean): Value? {
|
||||||
|
val sharedVarValue = this.getField(value, "element", expectedType, checkType)
|
||||||
|
if (sharedVarValue != null && isValueOfCorrectType(sharedVarValue, expectedType, checkType)) {
|
||||||
|
return sharedVarValue
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val localVariable = frame.visibleVariableByName(name)
|
||||||
|
if (localVariable != null) {
|
||||||
|
val eval4jValue = frame.getValue(localVariable).asValue()
|
||||||
|
if (eval4jValue.isSharedVar(asmType)) {
|
||||||
|
val sharedVarValue = eval4j.getValueForSharedVar(eval4jValue, asmType, checkType)
|
||||||
|
if (sharedVarValue != null) {
|
||||||
|
return sharedVarValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValueOfCorrectType(eval4jValue, asmType, checkType)) return eval4jValue
|
||||||
|
}
|
||||||
|
|
||||||
fun findCapturedVal(name: String): Value? {
|
fun findCapturedVal(name: String): Value? {
|
||||||
var result: Value? = null
|
var result: Value? = null
|
||||||
var thisObj: Value? = frame.thisObject().asValue()
|
var thisObj: Value? = frame.thisObject().asValue()
|
||||||
|
|
||||||
while (result == null && thisObj != null) {
|
while (result == null && thisObj != null) {
|
||||||
result = eval4j.getField(thisObj!!, name, asmType)
|
result = eval4j.getField(thisObj!!, name, asmType, checkType)
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
thisObj = eval4j.getField(thisObj!!, AsmUtil.CAPTURED_THIS_FIELD, null)
|
thisObj = eval4j.getField(thisObj!!, AsmUtil.CAPTURED_THIS_FIELD, null, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@@ -377,7 +397,15 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
|
|||||||
|
|
||||||
val capturedValName = getCapturedFieldName(name)
|
val capturedValName = getCapturedFieldName(name)
|
||||||
val capturedVal = findCapturedVal(capturedValName)
|
val capturedVal = findCapturedVal(capturedValName)
|
||||||
if (capturedVal != null) return capturedVal
|
if (capturedVal != null) {
|
||||||
|
if (capturedVal.isSharedVar(asmType)) {
|
||||||
|
val sharedVarValue = eval4j.getValueForSharedVar(capturedVal, asmType, checkType)
|
||||||
|
if (sharedVarValue != null) {
|
||||||
|
return sharedVarValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return capturedVal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ LineBreakpoint created at frameSharedVar.kt:7
|
|||||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! frameSharedVar.FrameSharedVarPackage
|
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! frameSharedVar.FrameSharedVarPackage
|
||||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
frameSharedVar.kt:6
|
frameSharedVar.kt:6
|
||||||
|
Compile bytecode for var1
|
||||||
package frameSharedVar
|
package frameSharedVar
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
@@ -17,6 +18,9 @@ fun foo(f: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PRINT_FRAME
|
// PRINT_FRAME
|
||||||
|
|
||||||
|
// EXPRESSION: var1
|
||||||
|
// RESULT: 1: I
|
||||||
frame = invoke():7, FrameSharedVarPackage$@packagePartHASH$main$1 {frameSharedVar}
|
frame = invoke():7, FrameSharedVarPackage$@packagePartHASH$main$1 {frameSharedVar}
|
||||||
this = this = {frameSharedVar.FrameSharedVarPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
this = this = {frameSharedVar.FrameSharedVarPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||||
field = $var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
field = $var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
LineBreakpoint created at frameSharedVarLocalVar.kt:7
|
||||||
|
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! frameSharedVarLocalVar.FrameSharedVarLocalVarPackage
|
||||||
|
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
|
frameSharedVarLocalVar.kt:6
|
||||||
|
Compile bytecode for var1
|
||||||
|
package frameSharedVarLocalVar
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
var var1 = 1
|
||||||
|
foo {
|
||||||
|
//Breakpoint!
|
||||||
|
var1 = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun foo(f: () -> Unit) {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRINT_FRAME
|
||||||
|
|
||||||
|
// EXPRESSION: var1
|
||||||
|
// RESULT: 1: I
|
||||||
|
frame = main():7, FrameSharedVarLocalVarPackage-@packagePartHASH {frameSharedVarLocalVar}
|
||||||
|
static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage-@packagePartHASH
|
||||||
|
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
||||||
|
local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||||
|
field = element: int = 1
|
||||||
|
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
|
|
||||||
|
Process finished with exit code 0
|
||||||
@@ -13,3 +13,6 @@ fun foo(f: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PRINT_FRAME
|
// PRINT_FRAME
|
||||||
|
|
||||||
|
// EXPRESSION: var1
|
||||||
|
// RESULT: 1: I
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package frameSharedVarLocalVar
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
var var1 = 1
|
||||||
|
foo {
|
||||||
|
//Breakpoint!
|
||||||
|
var1 = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun foo(f: () -> Unit) {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRINT_FRAME
|
||||||
|
|
||||||
|
// EXPRESSION: var1
|
||||||
|
// RESULT: 1: I
|
||||||
+6
@@ -266,6 +266,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
|||||||
doSingleBreakpointTest(fileName);
|
doSingleBreakpointTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("frameSharedVarLocalVar.kt")
|
||||||
|
public void testFrameSharedVarLocalVar() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/frameSharedVarLocalVar.kt");
|
||||||
|
doSingleBreakpointTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("frameSimple.kt")
|
@TestMetadata("frameSimple.kt")
|
||||||
public void testFrameSimple() throws Exception {
|
public void testFrameSimple() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/frameSimple.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/frameSimple.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user