Bug 318495 - add AST evaluation tracing
diff --git a/org.eclipse.jdt.debug/.options b/org.eclipse.jdt.debug/.options
index 66f229c..3ef5cf6 100644
--- a/org.eclipse.jdt.debug/.options
+++ b/org.eclipse.jdt.debug/.options
@@ -1,3 +1,6 @@
org.eclipse.jdt.debug/debug=false
org.eclipse.jdt.debug/debug/jdiEvents=false
org.eclipse.jdt.debug/debug/jdiRequestTimes=false
+org.eclipse.jdt.debug/debug/astEvaluations=false
+org.eclipse.jdt.debug/debug/astEvaluations/callingThreads=false
+
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
index b9c8650..8e722a4 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.debug.eval.ast.engine;
+import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -27,6 +28,7 @@
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventFilter;
import org.eclipse.debug.core.model.ITerminate;
+import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.IProblem;
@@ -50,6 +52,7 @@
import org.eclipse.jdt.debug.eval.ICompiledExpression;
import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.IEvaluationResult;
+import org.eclipse.jdt.internal.debug.core.JDIDebugOptions;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
@@ -111,6 +114,7 @@
* @see org.eclipse.jdt.debug.eval.IEvaluationEngine#evaluate(java.lang.String, org.eclipse.jdt.debug.core.IJavaStackFrame, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
*/
public void evaluate(String snippet, IJavaStackFrame frame, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ traceCaller(snippet, frame.getThread());
checkInterface(frame);
ICompiledExpression expression= getCompiledExpression(snippet, frame);
evaluateExpression(expression, frame, listener, evaluationDetail, hitBreakpoints);
@@ -120,9 +124,37 @@
* @see org.eclipse.jdt.debug.eval.IEvaluationEngine#evaluate(java.lang.String, org.eclipse.jdt.debug.core.IJavaObject, org.eclipse.jdt.debug.core.IJavaThread, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
*/
public void evaluate(String snippet, IJavaObject thisContext, IJavaThread thread, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ traceCaller(snippet, thread);
ICompiledExpression expression= getCompiledExpression(snippet, thisContext);
evaluateExpression(expression, thisContext, thread, listener, evaluationDetail, hitBreakpoints);
}
+
+ /**
+ * Writes a stack dump to trace the calling thread.
+ *
+ * @param snippet expression to evaluate
+ * @param thread thread to evaluate in
+ */
+ private void traceCaller(String snippet, IThread thread) {
+ if (JDIDebugOptions.DEBUG_AST_EVAL_THREAD_TRACE) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(JDIDebugOptions.FORMAT.format(new Date()));
+ buf.append(" : Evaluation Request Trace - Expression: "); //$NON-NLS-1$
+ buf.append(snippet);
+ buf.append("\n\tThread: "); //$NON-NLS-1$
+ try {
+ String name = thread.getName();
+ buf.append('[');
+ buf.append(name);
+ buf.append("] "); //$NON-NLS-1$
+ } catch (DebugException e) {
+ buf.append(thread.toString());
+ }
+ System.out.println(buf.toString());
+ System.out.flush();
+ Thread.dumpStack();
+ }
+ }
/**
* Checks if the stack frame is declared in an interface an aborts
@@ -143,6 +175,7 @@
* @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#evaluateExpression(org.eclipse.jdt.debug.eval.ICompiledExpression, org.eclipse.jdt.debug.core.IJavaStackFrame, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
*/
public void evaluateExpression(ICompiledExpression expression, IJavaStackFrame frame, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ traceCaller(expression.getSnippet(), frame.getThread());
RuntimeContext context = new RuntimeContext(getJavaProject(), frame);
doEvaluation(expression, context, (IJavaThread)frame.getThread(), listener, evaluationDetail, hitBreakpoints);
}
@@ -151,6 +184,7 @@
* @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#evaluateExpression(org.eclipse.jdt.debug.eval.ICompiledExpression, org.eclipse.jdt.debug.core.IJavaObject, org.eclipse.jdt.debug.core.IJavaThread, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
*/
public void evaluateExpression(ICompiledExpression expression, IJavaObject thisContext, IJavaThread thread, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ traceCaller(expression.getSnippet(), thread);
IRuntimeContext context = null;
if (thisContext instanceof IJavaArray) {
context = new ArrayRuntimeContext((IJavaArray) thisContext, thread, getJavaProject());
@@ -460,6 +494,33 @@
}
public void run() {
+ if (JDIDebugOptions.DEBUG_AST_EVAL) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(JDIDebugOptions.FORMAT.format(new Date()));
+ buf.append(" : AST Evaluation"); //$NON-NLS-1$
+ buf.append("\n\tExpression: "); //$NON-NLS-1$
+ buf.append(fExpression.getSnippet());
+ buf.append("\n\tThread: "); //$NON-NLS-1$
+ try {
+ String name = fThread.getName();
+ buf.append('[');
+ buf.append(name);
+ buf.append("] "); //$NON-NLS-1$
+ } catch (DebugException e) {
+ }
+ buf.append(fThread.toString());
+ buf.append("\n\tDetail: "); //$NON-NLS-1$
+ if (fEvaluationDetail == DebugEvent.EVALUATION) {
+ buf.append("EVALUATION"); //$NON-NLS-1$
+ } else if (fEvaluationDetail == DebugEvent.EVALUATION_IMPLICIT) {
+ buf.append("EVALUATION_IMPLICIT"); //$NON-NLS-1$
+ } else {
+ buf.append(fEvaluationDetail);
+ }
+ buf.append(" Hit Breakpoints: "); //$NON-NLS-1$
+ buf.append(fHitBreakpoints);
+ System.out.println(buf.toString());
+ }
EvaluationResult result = new EvaluationResult(ASTEvaluationEngine.this, fExpression.getSnippet(), fThread);
if (fExpression.hasErrors()) {
String[] errors = fExpression.getErrorMessages();
@@ -467,6 +528,18 @@
result.addError(errors[i]);
}
evaluationFinished(result);
+ if (JDIDebugOptions.DEBUG_AST_EVAL) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("\tErrors: "); //$NON-NLS-1$
+ for (int i = 0; i < errors.length; i++) {
+ if (i > 0) {
+ buf.append('\n');
+ }
+ buf.append("\t\t"); //$NON-NLS-1$
+ buf.append(errors[i]);
+ }
+ System.out.println(buf.toString());
+ }
return;
}
final Interpreter interpreter = new Interpreter(fExpression, fContext);
@@ -516,11 +589,13 @@
EvaluationRunnable er = new EvaluationRunnable();
CoreException exception = null;
+ long start = System.currentTimeMillis();
try {
fThread.runEvaluation(er, null, fEvaluationDetail, fHitBreakpoints);
} catch (DebugException e) {
exception = e;
}
+ long end = System.currentTimeMillis();
IJavaValue value = interpreter.getResult();
@@ -530,6 +605,12 @@
result.setTerminated(er.fTerminated);
if (exception != null) {
+ if (JDIDebugOptions.DEBUG_AST_EVAL) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("\tException: "); //$NON-NLS-1$
+ buf.append(exception.toString());
+ System.out.println(buf.toString());
+ }
if (exception instanceof DebugException) {
result.setException((DebugException)exception);
} else {
@@ -538,11 +619,24 @@
} else {
if (value != null) {
result.setValue(value);
+ if (JDIDebugOptions.DEBUG_AST_EVAL) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("\tResult: "); //$NON-NLS-1$
+ buf.append(value);
+ System.out.println(buf.toString());
+ }
} else {
result.addError(EvaluationEngineMessages.ASTEvaluationEngine_An_unknown_error_occurred_during_evaluation);
}
}
+ if (JDIDebugOptions.DEBUG_AST_EVAL) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("\tDuration: "); //$NON-NLS-1$
+ buf.append(end - start);
+ buf.append("ms"); //$NON-NLS-1$
+ System.out.println(buf.toString());
+ }
evaluationFinished(result);
}
diff --git a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/MirrorImpl.java b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/MirrorImpl.java
index a2b9053..5946c55 100644
--- a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/MirrorImpl.java
+++ b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/MirrorImpl.java
@@ -26,8 +26,6 @@
import org.eclipse.jdi.internal.jdwp.JdwpString;
import org.eclipse.jdt.internal.debug.core.JDIDebugOptions;
-import com.ibm.icu.text.DateFormat;
-import com.ibm.icu.text.SimpleDateFormat;
import com.sun.jdi.ClassNotPreparedException;
import com.sun.jdi.InternalException;
import com.sun.jdi.InvalidStackFrameException;
@@ -56,9 +54,6 @@
/** True if a Jdwp request has been sent to the VM and the response is not yet (fully) processed. */
private boolean fPendingJdwpRequest = false;
- // used for debug messages
- private static final DateFormat LOCAL_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //$NON-NLS-1$
-
/**
* Constructor only to be used by Virtual Machine objects: stores description of Mirror object and Virtual Machine.
*/
@@ -183,7 +178,7 @@
long recieved = System.currentTimeMillis();
if (JDIDebugOptions.DEBUG_JDI_REQUEST_TIMES) {
StringBuffer buf = new StringBuffer();
- buf.append(LOCAL_SDF.format(new Date(sent)));
+ buf.append(JDIDebugOptions.FORMAT.format(new Date(sent)));
buf.append(" JDI Request: "); //$NON-NLS-1$
buf.append(commandPacket.toString());
buf.append("\n\tResponse Time: "); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugOptions.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugOptions.java
index 8d484cf..70e2a9f 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugOptions.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugOptions.java
@@ -12,6 +12,9 @@
import org.eclipse.core.runtime.Platform;
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.SimpleDateFormat;
+
/**
* Debug flags in options file.
*
@@ -22,6 +25,11 @@
public static boolean DEBUG = false;
public static boolean DEBUG_JDI_EVENTS = false;
public static boolean DEBUG_JDI_REQUEST_TIMES = false;
+ public static boolean DEBUG_AST_EVAL = false;
+ public static boolean DEBUG_AST_EVAL_THREAD_TRACE = false;
+
+ // used to format debug messages
+ public static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //$NON-NLS-1$
public static void initDebugOptions() {
DEBUG = "true".equals(Platform.getDebugOption("org.eclipse.jdt.debug/debug")); //$NON-NLS-1$//$NON-NLS-2$
@@ -29,5 +37,9 @@
Platform.getDebugOption("org.eclipse.jdt.debug/debug/jdiEvents")); //$NON-NLS-1$
DEBUG_JDI_REQUEST_TIMES = DEBUG && "true".equals( //$NON-NLS-1$
Platform.getDebugOption("org.eclipse.jdt.debug/debug/jdiRequestTimes")); //$NON-NLS-1$
+ DEBUG_AST_EVAL = DEBUG && "true".equals( //$NON-NLS-1$
+ Platform.getDebugOption("org.eclipse.jdt.debug/debug/astEvaluations")); //$NON-NLS-1$
+ DEBUG_AST_EVAL_THREAD_TRACE = DEBUG && "true".equals( //$NON-NLS-1$
+ Platform.getDebugOption("org.eclipse.jdt.debug/debug/astEvaluations/callingThreads")); //$NON-NLS-1$
}
}