Skip to content

Commit

Permalink
* Modernize exception handling by pruning behavior applicable only to
Browse files Browse the repository at this point in the history
JDK6-

* Fixes #3240
  • Loading branch information
srikanth-sankaran committed Nov 4, 2024
1 parent 332f378 commit 3979325
Show file tree
Hide file tree
Showing 15 changed files with 171 additions and 361 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds {


// try statements
public static final int IsSubRoutineEscaping = Bit15;
public static final int IsFinallyBlockEscaping = Bit15;
public static final int IsTryBlockExiting = Bit30;

// for type declaration
Expand Down Expand Up @@ -280,7 +280,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public static final int DidResolve = Bit19;

// for return statement
public static final int IsAnySubRoutineEscaping = Bit30;
public static final int IsAnyFinallyBlockEscaping = Bit30;
public static final int IsSynchronized = Bit31;

// for synchronized statement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public abstract class BranchStatement extends Statement {

public char[] label;
public BranchLabel targetLabel;
public SubRoutineStatement[] subroutines;
public StatementWithFinallyBlock[] statementsWithFinallyBlock;
public int initStateIndex = -1;

/**
Expand All @@ -33,7 +33,7 @@ public BranchStatement(char[] label, int sourceStart,int sourceEnd) {
this.sourceEnd = sourceEnd;
}

protected void setSubroutineSwitchExpression(SubRoutineStatement sub) {
protected void setSubroutineSwitchExpression(StatementWithFinallyBlock sub) {
// Do nothing
}
protected void restartExceptionLabels(CodeStream codeStream) {
Expand All @@ -53,16 +53,16 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {

// generation of code responsible for invoking the finally
// blocks in sequence
if (this.subroutines != null){
for (int i = 0, max = this.subroutines.length; i < max; i++){
SubRoutineStatement sub = this.subroutines[i];
if (this.statementsWithFinallyBlock != null){
for (int i = 0, max = this.statementsWithFinallyBlock.length; i < max; i++){
StatementWithFinallyBlock sub = this.statementsWithFinallyBlock[i];
SwitchExpression se = sub.getSwitchExpression();
setSubroutineSwitchExpression(sub);
boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, this.targetLabel, this.initStateIndex, null);
boolean didEscape = sub.generateFinallyBlock(currentScope, codeStream, this.targetLabel, this.initStateIndex, null);
sub.setSwitchExpression(se);
if (didEscape) {
codeStream.recordPositionsFrom(pc, this.sourceStart);
SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
StatementWithFinallyBlock.reenterAllExceptionHandlers(this.statementsWithFinallyBlock, i, codeStream);
if (this.initStateIndex != -1) {
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
Expand All @@ -75,7 +75,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
// checkAndLoadSyntheticVars(codeStream);
codeStream.goto_(this.targetLabel);
codeStream.recordPositionsFrom(pc, this.sourceStart);
SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream);
StatementWithFinallyBlock.reenterAllExceptionHandlers(this.statementsWithFinallyBlock, -1, codeStream);
if (this.initStateIndex != -1) {
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.InsideSubRoutineFlowContext;
import org.eclipse.jdt.internal.compiler.flow.InsideStatementWithFinallyBlockFlowContext;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;

public class BreakStatement extends BranchStatement {
Expand Down Expand Up @@ -59,27 +59,27 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
this.targetLabel = targetContext.breakLabel();
FlowContext traversedContext = flowContext;
int subCount = 0;
this.subroutines = new SubRoutineStatement[5];
this.statementsWithFinallyBlock = new StatementWithFinallyBlock[5];

do {
SubRoutineStatement sub;
if ((sub = traversedContext.subroutine()) != null) {
if (subCount == this.subroutines.length) {
System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow
StatementWithFinallyBlock sub;
if ((sub = traversedContext.statementWithFinallyBlock()) != null) {
if (subCount == this.statementsWithFinallyBlock.length) {
System.arraycopy(this.statementsWithFinallyBlock, 0, (this.statementsWithFinallyBlock = new StatementWithFinallyBlock[subCount*2]), 0, subCount); // grow
}
this.subroutines[subCount++] = sub;
if (sub.isSubRoutineEscaping()) {
this.statementsWithFinallyBlock[subCount++] = sub;
if (sub.isFinallyBlockEscaping()) {
break;
}
}
traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
traversedContext.recordBreakTo(targetContext);

if (traversedContext instanceof InsideSubRoutineFlowContext) {
if (traversedContext instanceof InsideStatementWithFinallyBlockFlowContext) {
ASTNode node = traversedContext.associatedNode;
if (node instanceof TryStatement) {
TryStatement tryStatement = (TryStatement) node;
flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
flowInfo.addInitializationsFrom(tryStatement.finallyBlockInits); // collect inits
}
} else if (traversedContext == targetContext) {
// only record break info once accumulated through subroutines, and only against target context
Expand All @@ -89,8 +89,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
} while ((traversedContext = traversedContext.getLocalParent()) != null);

// resize subroutines
if (subCount != this.subroutines.length) {
System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount);
if (subCount != this.statementsWithFinallyBlock.length) {
System.arraycopy(this.statementsWithFinallyBlock, 0, (this.statementsWithFinallyBlock = new StatementWithFinallyBlock[subCount]), 0, subCount);
}
return FlowInfo.DEAD_END;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.InsideSubRoutineFlowContext;
import org.eclipse.jdt.internal.compiler.flow.InsideStatementWithFinallyBlockFlowContext;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;

public class ContinueStatement extends BranchStatement {
Expand Down Expand Up @@ -63,26 +63,26 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
this.targetLabel = targetContext.continueLabel();
FlowContext traversedContext = flowContext;
int subCount = 0;
this.subroutines = new SubRoutineStatement[5];
this.statementsWithFinallyBlock = new StatementWithFinallyBlock[5];

do {
SubRoutineStatement sub;
if ((sub = traversedContext.subroutine()) != null) {
if (subCount == this.subroutines.length) {
System.arraycopy(this.subroutines, 0, this.subroutines = new SubRoutineStatement[subCount*2], 0, subCount); // grow
StatementWithFinallyBlock sub;
if ((sub = traversedContext.statementWithFinallyBlock()) != null) {
if (subCount == this.statementsWithFinallyBlock.length) {
System.arraycopy(this.statementsWithFinallyBlock, 0, this.statementsWithFinallyBlock = new StatementWithFinallyBlock[subCount*2], 0, subCount); // grow
}
this.subroutines[subCount++] = sub;
if (sub.isSubRoutineEscaping()) {
this.statementsWithFinallyBlock[subCount++] = sub;
if (sub.isFinallyBlockEscaping()) {
break;
}
}
traversedContext.recordReturnFrom(flowInfo.unconditionalInits());

if (traversedContext instanceof InsideSubRoutineFlowContext) {
if (traversedContext instanceof InsideStatementWithFinallyBlockFlowContext) {
ASTNode node = traversedContext.associatedNode;
if (node instanceof TryStatement) {
TryStatement tryStatement = (TryStatement) node;
flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
flowInfo.addInitializationsFrom(tryStatement.finallyBlockInits); // collect inits
}
} else if (traversedContext == targetContext) {
// only record continue info once accumulated through subroutines, and only against target context
Expand All @@ -92,8 +92,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
} while ((traversedContext = traversedContext.getLocalParent()) != null);

// resize subroutines
if (subCount != this.subroutines.length) {
System.arraycopy(this.subroutines, 0, this.subroutines = new SubRoutineStatement[subCount], 0, subCount);
if (subCount != this.statementsWithFinallyBlock.length) {
System.arraycopy(this.statementsWithFinallyBlock, 0, this.statementsWithFinallyBlock = new StatementWithFinallyBlock[subCount], 0, subCount);
}
return FlowInfo.DEAD_END;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
import org.eclipse.jdt.internal.compiler.flow.InsideSubRoutineFlowContext;
import org.eclipse.jdt.internal.compiler.flow.InsideStatementWithFinallyBlockFlowContext;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
Expand All @@ -64,7 +64,7 @@
public class ReturnStatement extends Statement {

public Expression expression;
public SubRoutineStatement[] subroutines;
public StatementWithFinallyBlock[] statementsWithFinallyBlock;
public LocalVariableBinding saveValueVariable;
public int initStateIndex = -1;
private final boolean implicitReturn;
Expand Down Expand Up @@ -119,18 +119,18 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
boolean hasValueToSave = needValueStore();
boolean noAutoCloseables = true;
do {
SubRoutineStatement sub;
if ((sub = traversedContext.subroutine()) != null) {
if (this.subroutines == null){
this.subroutines = new SubRoutineStatement[5];
StatementWithFinallyBlock sub;
if ((sub = traversedContext.statementWithFinallyBlock()) != null) {
if (this.statementsWithFinallyBlock == null){
this.statementsWithFinallyBlock = new StatementWithFinallyBlock[5];
}
if (subCount == this.subroutines.length) {
System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow
if (subCount == this.statementsWithFinallyBlock.length) {
System.arraycopy(this.statementsWithFinallyBlock, 0, (this.statementsWithFinallyBlock = new StatementWithFinallyBlock[subCount*2]), 0, subCount); // grow
}
this.subroutines[subCount++] = sub;
if (sub.isSubRoutineEscaping()) {
this.statementsWithFinallyBlock[subCount++] = sub;
if (sub.isFinallyBlockEscaping()) {
saveValueNeeded = false;
this.bits |= ASTNode.IsAnySubRoutineEscaping;
this.bits |= ASTNode.IsAnyFinallyBlockEscaping;
break;
}
if (sub instanceof TryStatement) {
Expand All @@ -141,13 +141,13 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
traversedContext.recordReturnFrom(flowInfo.unconditionalInits());

if (traversedContext instanceof InsideSubRoutineFlowContext) {
if (traversedContext instanceof InsideStatementWithFinallyBlockFlowContext) {
ASTNode node = traversedContext.associatedNode;
if (node instanceof SynchronizedStatement) {
this.bits |= ASTNode.IsSynchronized;
} else if (node instanceof TryStatement) {
TryStatement tryStatement = (TryStatement) node;
flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
flowInfo.addInitializationsFrom(tryStatement.finallyBlockInits); // collect inits
if (hasValueToSave) {
if (this.saveValueVariable == null){ // closest subroutine secret variable is used
prepareSaveValueLocation(tryStatement);
Expand All @@ -167,8 +167,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
} while ((traversedContext = traversedContext.getLocalParent()) != null);

// resize subroutines
if ((this.subroutines != null) && (subCount != this.subroutines.length)) {
System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount);
if ((this.statementsWithFinallyBlock != null) && (subCount != this.statementsWithFinallyBlock.length)) {
System.arraycopy(this.statementsWithFinallyBlock, 0, (this.statementsWithFinallyBlock = new StatementWithFinallyBlock[subCount]), 0, subCount);
}

// secret local variable for return value (note that this can only occur in a real method)
Expand Down Expand Up @@ -246,14 +246,14 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
}

// generation of code responsible for invoking the finally blocks in sequence
if (this.subroutines != null) {
if (this.statementsWithFinallyBlock != null) {
Object reusableJSRTarget = this.expression == null ? (Object)TypeBinding.VOID : this.expression.reusableJSRTarget();
for (int i = 0, max = this.subroutines.length; i < max; i++) {
SubRoutineStatement sub = this.subroutines[i];
boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, reusableJSRTarget, this.initStateIndex, this.saveValueVariable);
for (int i = 0, max = this.statementsWithFinallyBlock.length; i < max; i++) {
StatementWithFinallyBlock sub = this.statementsWithFinallyBlock[i];
boolean didEscape = sub.generateFinallyBlock(currentScope, codeStream, reusableJSRTarget, this.initStateIndex, this.saveValueVariable);
if (didEscape) {
codeStream.recordPositionsFrom(pc, this.sourceStart);
SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
StatementWithFinallyBlock.reenterAllExceptionHandlers(this.statementsWithFinallyBlock, i, codeStream);
return;
}
}
Expand All @@ -276,7 +276,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream);
StatementWithFinallyBlock.reenterAllExceptionHandlers(this.statementsWithFinallyBlock, -1, codeStream);
}

/**
Expand All @@ -303,7 +303,7 @@ private boolean needValueStore() {
public boolean needValue() {
return this.saveValueVariable != null
|| (this.bits & ASTNode.IsSynchronized) != 0
|| ((this.bits & ASTNode.IsAnySubRoutineEscaping) == 0);
|| ((this.bits & ASTNode.IsAnyFinallyBlockEscaping) == 0);
}

public void prepareSaveValueLocation(TryStatement targetTryStatement){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;

/**
* Extra behavior for statements which are generating subroutines
* Extra behavior for statements which have a postscript - e.g., try blocks have finally; synchronized statements have hidden finally blocks that call monitorexit etc.
*/
public abstract class SubRoutineStatement extends Statement {
public abstract class StatementWithFinallyBlock extends Statement {

public static void reenterAllExceptionHandlers(SubRoutineStatement[] subroutines, int max, CodeStream codeStream) {
if (subroutines == null) return;
if (max < 0) max = subroutines.length;
public static void reenterAllExceptionHandlers(StatementWithFinallyBlock[] statements, int max, CodeStream codeStream) {
if (statements == null) return;
if (max < 0) max = statements.length;
for (int i = 0; i < max; i++) {
SubRoutineStatement sub = subroutines[i];
sub.enterAnyExceptionHandler(codeStream);
sub.enterDeclaredExceptionHandlers(codeStream);
StatementWithFinallyBlock stmt = statements[i];
stmt.enterAnyExceptionHandler(codeStream);
stmt.enterDeclaredExceptionHandlers(codeStream);
}
}

Expand Down Expand Up @@ -61,12 +61,12 @@ public void exitDeclaredExceptionHandlers(CodeStream codeStream) {


/**
* Generate an invocation of a subroutine (e.g. jsr finally) in current context.
* @return boolean, <code>true</code> if the generated code will abrupt completion
* Generate the postscript in current context.
* @return boolean, <code>true</code> if the generated code will complete abruptly.
*/
public abstract boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal);
public abstract boolean generateFinallyBlock(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal);

public abstract boolean isSubRoutineEscaping();
public abstract boolean isFinallyBlockEscaping();

public void placeAllAnyExceptionHandler() {
this.anyExceptionLabel.place();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.InsideSubRoutineFlowContext;
import org.eclipse.jdt.internal.compiler.flow.InsideStatementWithFinallyBlockFlowContext;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;

public class SynchronizedStatement extends SubRoutineStatement {
public class SynchronizedStatement extends StatementWithFinallyBlock { // comes with a hidden finally block that contains the monitorexit sequence

public Expression expression;
public Block block;
Expand Down Expand Up @@ -72,7 +72,7 @@ public FlowInfo analyseCode(
flowInfo =
this.block.analyseCode(
this.scope,
new InsideSubRoutineFlowContext(flowContext, this),
new InsideStatementWithFinallyBlockFlowContext(flowContext, this),
expressionFlowInfo);

this.mergedSynchronizedInitStateIndex =
Expand All @@ -87,7 +87,7 @@ public FlowInfo analyseCode(
}

@Override
public boolean isSubRoutineEscaping() {
public boolean isFinallyBlockEscaping() {
return false;
}

Expand Down Expand Up @@ -174,10 +174,10 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
}

/**
* @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding)
* @see StatementWithFinallyBlock#generateFinallyBlock(BlockScope, CodeStream, Object, int, LocalVariableBinding)
*/
@Override
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) {
public boolean generateFinallyBlock(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) {
codeStream.load(this.synchroVariable);
codeStream.monitorexit();
exitAnyExceptionHandler();
Expand Down
Loading

0 comments on commit 3979325

Please sign in to comment.