Skip to content

Commit

Permalink
+ still more complete sync between outer-inner resources
Browse files Browse the repository at this point in the history
  • Loading branch information
stephan-herrmann committed Jan 10, 2024
1 parent a98d151 commit 8d231f1
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ public static void analyseCloseableAllocation(BlockScope scope, FlowInfo flowInf
* Check if a message send acquires a closeable from its receiver, see:
* Bug 463320 - [compiler][resource] potential "resource leak" problem disappears when local variable inlined
*/
public static FlowInfo analyseCloseableAcquisition(BlockScope scope, FlowInfo flowInfo, MessageSend acquisition) {
public static FlowInfo analyseCloseableAcquisition(BlockScope scope, FlowInfo flowInfo, FlowContext flowContext, MessageSend acquisition) {
if (isFluentMethod(acquisition.binding)) {
// share the existing close tracker of the receiver (if any):
acquisition.closeTracker = findCloseTracker(scope, flowInfo, acquisition.receiver);
Expand Down Expand Up @@ -542,7 +542,7 @@ public static FlowInfo analyseCloseableAcquisition(BlockScope scope, FlowInfo fl
tracker.acquisition = acquisition;
FlowInfo outsideInfo = flowInfo.copy();
outsideInfo.markAsDefinitelyNonNull(tracker.binding);
flowInfo.markAsDefinitelyNull(tracker.binding);
tracker.markNullStatus(flowInfo, flowContext, FlowInfo.NULL);
return FlowInfo.conditional(outsideInfo, flowInfo);
}
}
Expand Down Expand Up @@ -619,13 +619,13 @@ private static void handleRegularResource(BlockScope scope, FlowInfo flowInfo, F
int finallyNullStatus = enclosingFinallyInfo.nullStatus(presetTracker.binding);
enclosingFinallyInfo.markNullStatus(local.closeTracker.binding, finallyNullStatus);
}
presetTracker.markUnknown(flowInfo, flowContext); // no longer relevant in this flow
presetTracker.markNullStatus(flowInfo, flowContext, FlowInfo.UNKNOWN); // no longer relevant in this flow
}
}
} else {
allocation.closeTracker = new FakedTrackingVariable(scope, allocation, flowInfo, FlowInfo.UNKNOWN); // no local available, closeable is unassigned
}
flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding);
allocation.closeTracker.markNullStatus(flowInfo, flowContext, FlowInfo.NULL);
}

/** Was this FTV created from the finally block of the current context? */
Expand Down Expand Up @@ -771,7 +771,7 @@ public static void handleResourceAssignment(BlockScope scope, FlowInfo upstreamI
// re-assigning from a fresh value, mark as not-closed again:
if ((previousTracker.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE|FOREACH_ELEMENT_VAR)) == 0
&& flowInfo.hasNullInfoFor(previousTracker.binding)) // avoid spilling info into a branch that doesn't see the corresponding resource
flowInfo.markAsDefinitelyNull(previousTracker.binding);
previousTracker.markNullStatus(flowInfo, flowContext, FlowInfo.NULL);
local.closeTracker = analyseCloseableExpression(scope, flowInfo, flowContext, useAnnotations, local, location, rhs, previousTracker);
}
} else { // 3. no re-use, create a fresh tracking variable:
Expand All @@ -781,7 +781,7 @@ public static void handleResourceAssignment(BlockScope scope, FlowInfo upstreamI
if (!useAnnotations) {
// a fresh resource, mark as not-closed:
if ((rhsTrackVar.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE|FOREACH_ELEMENT_VAR)) == 0)
flowInfo.markAsDefinitelyNull(rhsTrackVar.binding);
rhsTrackVar.markNullStatus(flowInfo, flowContext, FlowInfo.NULL);
}
// TODO(stephan): this might be useful, but I could not find a test case for it:
// if (flowContext.initsOnFinally != null)
Expand Down Expand Up @@ -843,7 +843,7 @@ public static void handleResourceFieldAssignment(BlockScope scope, FlowInfo flow
}
if (field != null) {
if (!field.isStatic() && (field.tagBits & TagBits.AnnotationOwning) != 0) {
flowInfo.markAsDefinitelyNonNull(rhsTrackVar.binding);
rhsTrackVar.markNullStatus(flowInfo, flowContext, FlowInfo.NON_NULL);
} else {
rhsTrackVar.markAsShared();
}
Expand Down Expand Up @@ -1186,10 +1186,10 @@ public void markClose(FlowInfo flowInfo, FlowContext flowContext) {
});
}

private void markUnknown(FlowInfo flowInfo, FlowContext flowContext) {
public void markNullStatus(FlowInfo flowInfo, FlowContext flowContext, int status) {
markAllConnected(current -> {
flowInfo.markAsDefinitelyUnknown(current.binding);
flowContext.markFinallyNullStatus(current.binding, FlowInfo.UNKNOWN);
flowInfo.markNullStatus(current.binding, status);
flowContext.markFinallyNullStatus(current.binding, status);
});
}

Expand Down Expand Up @@ -1245,7 +1245,7 @@ public static FlowInfo markPassedToOutside(BlockScope scope, Expression expressi
ftv.globalClosingState |= flag;
if (scope.methodScope() != ftv.methodScope)
ftv.globalClosingState |= CLOSED_IN_NESTED_METHOD;
infoResourceIsClosed.markAsDefinitelyNonNull(ftv.binding);
ftv.markNullStatus(flowInfo, flowContext, FlowInfo.NON_NULL);
});
if (owned) {
return infoResourceIsClosed; // don't let downstream signal any problems on this flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
// after having analysed exceptions above start tracking newly allocated resource:
if (analyseResources && FakedTrackingVariable.isAnyCloseable(this.resolvedType))
flowInfo = FakedTrackingVariable.analyseCloseableAcquisition(currentScope, flowInfo, this);
flowInfo = FakedTrackingVariable.analyseCloseableAcquisition(currentScope, flowInfo, flowContext, this);

manageSyntheticAccessIfNecessary(currentScope, flowInfo);
// account for pot. exceptions thrown by method execution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1337,4 +1337,28 @@ static void test3(String name) throws Exception {
""",
null);
}
public void testWrappingTwoResources() {
runLeakTestWithAnnotations(
new String[] {
"X.java",
"""
import java.io.*;
import org.eclipse.jdt.annotation.*;
public class X implements AutoCloseable {
private final @Owning DataInputStream fDataIn;
private final @Owning DataOutputStream fDataOut;
public X(@Owning InputStream in, @Owning OutputStream out) {
fDataIn = new DataInputStream(new BufferedInputStream(in));
fDataOut = new DataOutputStream(new BufferedOutputStream(out));
}
public void close() throws IOException {
fDataIn.close();
fDataOut.close();
}
}
"""
},
"",
null);
}
}

0 comments on commit 8d231f1

Please sign in to comment.