-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PR2 of conditional BP #154
Conversation
andxu
commented
Mar 12, 2018
- Fix the issue when the condition is updated
- Add a cache to the compiled expression for conditional breakpoint.
@@ -31,6 +31,9 @@ | |||
private List<IBreakpoint> breakpoints; | |||
private HashMap<String, HashMap<String, IBreakpoint>> sourceToBreakpoints; | |||
private AtomicInteger nextBreakpointId = new AtomicInteger(1); | |||
// BreakpointManager is the owner class of the breakpoint to compiled expression map, it will remove | |||
// the breakpoint from this map if the breakpoint is removed or changing its condition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the breakpoint is removed or changing its condition ==> if the breakpoint is removed or its condition is changed
…am is stopped at the exception 2. update a comment
} | ||
|
||
if (!StringUtils.equals(toAdds[i].getCondition(), added[i].getCondition())) { | ||
manager.updateConditionCompiledExpression(added[i], toAdds[i].getCondition()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is strange put the hitCount update in here while keep the condition update in other places. The logic is mixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because updating condition will need to clear the expression cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setHitCount contains the logic to update hit count in jvm, it is not a pure set function.
} | ||
|
||
if (project == null) { | ||
new IllegalStateException(String.format("Project %s cannot be found.", projectName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why new a unused exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will use exception for the failure of initialization to debugTarget
} | ||
} | ||
|
||
if (debugTarget == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The outside is already have this logic
debugTarget == null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have two if blocks with the same condition to check whether debugTarget is null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Old issue in previous code, will fix it.
@@ -178,6 +188,37 @@ public void clearState(ThreadReference thread) { | |||
} | |||
} | |||
|
|||
private boolean ensureDebugTarget(VirtualMachine vm) { | |||
String projectName = (String) options.get(Constants.PROJECTNAME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If debugTarget is not null, this line is not necessary ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
2. fix the issue of a dirty evaluation environment cause the next evaluation failure.
* | ||
* @return the compiled expression map | ||
*/ | ||
public Map<IBreakpoint, Object> getBreakpointExpressionMap() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the cache is only used by the evaluation Provider, should it be better put insider the evaluation provider?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the keys are managed by breakpoint manager, and the values are managed by evaluation evaluation provider, I don't think its better for breakpoint manager to reference JdtEvaluationProvider
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JDT are storing expression in JavaLineBreakpoint@fCompiledExpressions
/**
* The map of cached compiled expressions (ICompiledExpression) for this
* breakpoint, keyed by thread. This value must be cleared every time the
* breakpoint is added to a target.
*/
private Map<IJavaThread, ICompiledExpression> fCompiledExpressions = new HashMap<>();
ASTEvaluationEngine engine = new ASTEvaluationEngine(project, debugTarget); | ||
ICompiledExpression ie = (ICompiledExpression) breakpointExpressionMap | ||
.computeIfAbsent(breakpoint, bp -> engine.getCompiledExpression(bp.getCondition(), stackframe)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return failureFuture and internalEvaluate result are two different instance. The client cannot hoop up with both future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done with a CompletableFuture parameter in internalEvaluate
@@ -31,6 +31,9 @@ | |||
private List<IBreakpoint> breakpoints; | |||
private HashMap<String, HashMap<String, IBreakpoint>> sourceToBreakpoints; | |||
private AtomicInteger nextBreakpointId = new AtomicInteger(1); | |||
// BreakpointManager is the owner class of the breakpoint to compiled expression map, it will remove | |||
// the breakpoint from this map if the breakpoint is removed or its condition is changed | |||
private Map<IBreakpoint, Object> breakpointExpressionMap = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the breakpoint manager maintaining the cache map but not the evaluation engine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cache should be kept by evaluation engine. The BreakpointManger notifies the engine to invalidate cache entries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because evaluation engine has no information about when the breakpoint is removed or updated.
} | ||
} | ||
|
||
if (debugTarget == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have two if blocks with the same condition to check whether debugTarget is null?
@@ -178,6 +188,37 @@ public void clearState(ThreadReference thread) { | |||
} | |||
} | |||
|
|||
private boolean ensureDebugTarget(VirtualMachine vm) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of ensureDebugTarget is never referenced anywhere. In the implementation, you use both exception and return value to indicate success, which is not recommended.
'ensure' means make sure something is actually there. When the function is not able to ensure that, an exception should be thrown. So please only use exceptions and the return value should be void.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
if (launch == null) { | ||
launch = createILaunchMock(project); | ||
} | ||
public CompletableFuture<Value> evaluateForBreakpoint(IBreakpoint breakpoint, ThreadReference thread, Map<IBreakpoint, Object> breakpointExpressionMap) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference of evaluating and evaluating for breakpoints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because conditional breakpoint will be executed multiple time inside a loop(eval and cont), and the condition and location don't change, we need to optimize the conditional breakpoint, consider the following case, the i == 1000 will be evaluated 999 times before the breakpoint is to hit.
for (; i < 1000 + 1; i++) {
if (i == 1000) { # conditional BP of i == 1000
System.out.println( "1111" );
}
}
2. keep only one CompletableFuture in evaluate