|
Lines 27-32
Link Here
|
| 27 |
|
27 |
|
| 28 |
static final char[] SECRET_RETURN_ADDRESS_NAME = " returnAddress".toCharArray(); //$NON-NLS-1$ |
28 |
static final char[] SECRET_RETURN_ADDRESS_NAME = " returnAddress".toCharArray(); //$NON-NLS-1$ |
| 29 |
static final char[] SECRET_ANY_HANDLER_NAME = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$ |
29 |
static final char[] SECRET_ANY_HANDLER_NAME = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$ |
|
|
30 |
static final char[] SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME = " primaryException".toCharArray(); //$NON-NLS-1$ |
| 31 |
static final char[] SECRET_TEMPORARY_THROWABLE_VARIABLE_NAME = " temporaryThrowable".toCharArray(); //$NON-NLS-1$; |
| 30 |
static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$ |
32 |
static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$ |
| 31 |
|
33 |
|
| 32 |
private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0]; |
34 |
private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0]; |
|
Lines 69-74
Link Here
|
| 69 |
int preTryInitStateIndex = -1; |
71 |
int preTryInitStateIndex = -1; |
| 70 |
int naturalExitMergeInitStateIndex = -1; |
72 |
int naturalExitMergeInitStateIndex = -1; |
| 71 |
int[] catchExitInitStateIndexes; |
73 |
int[] catchExitInitStateIndexes; |
|
|
74 |
private LocalVariableBinding primaryExceptionVariable; |
| 75 |
private LocalVariableBinding temporaryThrowableVariable; |
| 76 |
private ExceptionLabel[] resourceBlockLabels; |
| 72 |
|
77 |
|
| 73 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
78 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
| 74 |
|
79 |
|
|
Lines 85-90
Link Here
|
| 85 |
if (this.anyExceptionVariable != null) { |
90 |
if (this.anyExceptionVariable != null) { |
| 86 |
this.anyExceptionVariable.useFlag = LocalVariableBinding.USED; |
91 |
this.anyExceptionVariable.useFlag = LocalVariableBinding.USED; |
| 87 |
} |
92 |
} |
|
|
93 |
if (this.primaryExceptionVariable != null) { |
| 94 |
this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED; |
| 95 |
} |
| 96 |
if (this.temporaryThrowableVariable != null) { |
| 97 |
this.temporaryThrowableVariable.useFlag = LocalVariableBinding.USED; |
| 98 |
} |
| 88 |
if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused |
99 |
if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused |
| 89 |
this.returnAddressVariable.useFlag = LocalVariableBinding.USED; |
100 |
this.returnAddressVariable.useFlag = LocalVariableBinding.USED; |
| 90 |
} |
101 |
} |
|
Lines 106-111
Link Here
|
| 106 |
|
117 |
|
| 107 |
for (int i = 0, max = this.resources.length; i < max; i++) { |
118 |
for (int i = 0, max = this.resources.length; i < max; i++) { |
| 108 |
flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); |
119 |
flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); |
|
|
120 |
this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. |
| 109 |
TypeBinding type = this.resources[i].binding.type; |
121 |
TypeBinding type = this.resources[i].binding.type; |
| 110 |
if (type != null && type.isValidBinding()) { |
122 |
if (type != null && type.isValidBinding()) { |
| 111 |
ReferenceBinding binding = (ReferenceBinding) type; |
123 |
ReferenceBinding binding = (ReferenceBinding) type; |
|
Lines 229-234
Link Here
|
| 229 |
|
241 |
|
| 230 |
for (int i = 0, max = this.resources.length; i < max; i++) { |
242 |
for (int i = 0, max = this.resources.length; i < max; i++) { |
| 231 |
flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); |
243 |
flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); |
|
|
244 |
this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. |
| 232 |
TypeBinding type = this.resources[i].binding.type; |
245 |
TypeBinding type = this.resources[i].binding.type; |
| 233 |
if (type != null && type.isValidBinding()) { |
246 |
if (type != null && type.isValidBinding()) { |
| 234 |
ReferenceBinding binding = (ReferenceBinding) type; |
247 |
ReferenceBinding binding = (ReferenceBinding) type; |
|
Lines 425-431
Link Here
|
| 425 |
// generate the try block |
438 |
// generate the try block |
| 426 |
try { |
439 |
try { |
| 427 |
this.declaredExceptionLabels = exceptionLabels; |
440 |
this.declaredExceptionLabels = exceptionLabels; |
|
|
441 |
int resourceCount = this.resources.length; |
| 442 |
if (resourceCount > 0) { |
| 443 |
this.resourceBlockLabels = new ExceptionLabel[resourceCount + 1]; |
| 444 |
codeStream.aconst_null(); |
| 445 |
codeStream.store(this.primaryExceptionVariable, false /* value not required */); |
| 446 |
codeStream.addVariable(this.primaryExceptionVariable); |
| 447 |
codeStream.aconst_null(); |
| 448 |
codeStream.store(this.temporaryThrowableVariable, false /* value not required */); |
| 449 |
codeStream.addVariable(this.temporaryThrowableVariable); |
| 450 |
for (int i = 0; i <= resourceCount; i++) { |
| 451 |
this.resourceBlockLabels[i] = new ExceptionLabel(codeStream, this.scope.getJavaLangThrowable()); |
| 452 |
this.resourceBlockLabels[i].placeStart(); |
| 453 |
if (i < resourceCount) { |
| 454 |
this.resources[i].generateCode(this.scope, codeStream); |
| 455 |
} |
| 456 |
} |
| 457 |
} |
| 428 |
this.tryBlock.generateCode(this.scope, codeStream); |
458 |
this.tryBlock.generateCode(this.scope, codeStream); |
|
|
459 |
if (resourceCount > 0) { |
| 460 |
for (int i = resourceCount; i >= 0; i--) { |
| 461 |
BranchLabel exitLabel = new BranchLabel(codeStream); |
| 462 |
this.resourceBlockLabels[i].placeEnd(); |
| 463 |
|
| 464 |
LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null; |
| 465 |
if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { |
| 466 |
if (i > 0) { |
| 467 |
codeStream.load(localVariable); |
| 468 |
codeStream.ifnull(exitLabel); |
| 469 |
codeStream.load(localVariable); |
| 470 |
codeStream.invokeAutoCloseableClose(localVariable.type); |
| 471 |
} |
| 472 |
codeStream.goto_(exitLabel); |
| 473 |
} |
| 474 |
codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); |
| 475 |
this.resourceBlockLabels[i].place(); |
| 476 |
BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream); |
| 477 |
codeStream.store(this.temporaryThrowableVariable, false); |
| 478 |
codeStream.load(this.primaryExceptionVariable); |
| 479 |
codeStream.ifnonnull(elseLabel); |
| 480 |
codeStream.load(this.temporaryThrowableVariable); |
| 481 |
codeStream.store(this.primaryExceptionVariable, false); |
| 482 |
codeStream.goto_(postElseLabel); |
| 483 |
elseLabel.place(); |
| 484 |
codeStream.load(this.primaryExceptionVariable); |
| 485 |
codeStream.load(this.temporaryThrowableVariable); |
| 486 |
codeStream.if_acmpeq(postElseLabel); |
| 487 |
codeStream.load(this.primaryExceptionVariable); |
| 488 |
codeStream.load(this.temporaryThrowableVariable); |
| 489 |
codeStream.invokeThrowableAddSuppressed(); |
| 490 |
postElseLabel.place(); |
| 491 |
if (i > 0) { |
| 492 |
// inline resource close here rather than bracketing the current catch block with a try region. |
| 493 |
BranchLabel postCloseLabel = new BranchLabel(codeStream); |
| 494 |
codeStream.load(localVariable); |
| 495 |
codeStream.ifnull(postCloseLabel); |
| 496 |
codeStream.load(localVariable); |
| 497 |
codeStream.invokeAutoCloseableClose(localVariable.type); |
| 498 |
codeStream.removeVariable(localVariable); |
| 499 |
postCloseLabel.place(); |
| 500 |
} |
| 501 |
codeStream.load(this.primaryExceptionVariable); |
| 502 |
codeStream.athrow(); |
| 503 |
exitLabel.place(); |
| 504 |
} |
| 505 |
codeStream.removeVariable(this.primaryExceptionVariable); |
| 506 |
codeStream.removeVariable(this.temporaryThrowableVariable); |
| 507 |
} |
| 429 |
} finally { |
508 |
} finally { |
| 430 |
this.declaredExceptionLabels = null; |
509 |
this.declaredExceptionLabels = null; |
| 431 |
} |
510 |
} |
|
Lines 806-816
Link Here
|
| 806 |
this.scope = new BlockScope(upperScope); |
885 |
this.scope = new BlockScope(upperScope); |
| 807 |
|
886 |
|
| 808 |
BlockScope finallyScope = null; |
887 |
BlockScope finallyScope = null; |
| 809 |
|
888 |
BlockScope resourceManagementScope = null; |
| 810 |
// resolve all resources and inject them into separate scopes |
889 |
int resourceCount = this.resources.length; |
| 811 |
BlockScope localScope = new BlockScope(this.scope); |
890 |
if (resourceCount > 0) { |
| 812 |
for (int i = 0, max = this.resources.length; i < max; i++) { |
891 |
resourceManagementScope = new BlockScope(this.scope); |
| 813 |
this.resources[i].resolve(localScope); |
892 |
this.primaryExceptionVariable = |
|
|
893 |
new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); |
| 894 |
resourceManagementScope.addLocalVariable(this.primaryExceptionVariable); |
| 895 |
this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable |
| 896 |
this.temporaryThrowableVariable = |
| 897 |
new LocalVariableBinding(TryStatement.SECRET_TEMPORARY_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); |
| 898 |
resourceManagementScope.addLocalVariable(this.temporaryThrowableVariable); |
| 899 |
this.temporaryThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable |
| 900 |
} |
| 901 |
for (int i = 0; i < resourceCount; i++) { |
| 902 |
this.resources[i].resolve(resourceManagementScope); |
| 814 |
LocalVariableBinding localVariableBinding = this.resources[i].binding; |
903 |
LocalVariableBinding localVariableBinding = this.resources[i].binding; |
| 815 |
if (localVariableBinding != null && localVariableBinding.isValidBinding()) { |
904 |
if (localVariableBinding != null && localVariableBinding.isValidBinding()) { |
| 816 |
localVariableBinding.modifiers |= ClassFileConstants.AccFinal; |
905 |
localVariableBinding.modifiers |= ClassFileConstants.AccFinal; |
|
Lines 826-834
Link Here
|
| 826 |
localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); |
915 |
localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); |
| 827 |
} |
916 |
} |
| 828 |
} |
917 |
} |
| 829 |
localScope = new BlockScope(localScope, 1); |
|
|
| 830 |
} |
918 |
} |
| 831 |
BlockScope tryScope = localScope; |
919 |
BlockScope tryScope = new BlockScope(resourceManagementScope != null ? resourceManagementScope : this.scope); |
| 832 |
|
920 |
|
| 833 |
if (this.finallyBlock != null) { |
921 |
if (this.finallyBlock != null) { |
| 834 |
if (this.finallyBlock.isEmptyBlock()) { |
922 |
if (this.finallyBlock.isEmptyBlock()) { |
|
Lines 875-889
Link Here
|
| 875 |
this.finallyBlock.resolveUsing(finallyScope); |
963 |
this.finallyBlock.resolveUsing(finallyScope); |
| 876 |
// force the finally scope to have variable positions shifted after its try scope and catch ones |
964 |
// force the finally scope to have variable positions shifted after its try scope and catch ones |
| 877 |
int shiftScopesLength = this.catchArguments == null ? 1 : this.catchArguments.length + 1; |
965 |
int shiftScopesLength = this.catchArguments == null ? 1 : this.catchArguments.length + 1; |
| 878 |
shiftScopesLength += this.resources.length; |
|
|
| 879 |
finallyScope.shiftScopes = new BlockScope[shiftScopesLength]; |
966 |
finallyScope.shiftScopes = new BlockScope[shiftScopesLength]; |
| 880 |
for (int i = 0, max = this.resources.length; i < max; i++) { |
967 |
finallyScope.shiftScopes[0] = tryScope; |
| 881 |
LocalVariableBinding localVariableBinding = this.resources[i].binding; |
|
|
| 882 |
if (localVariableBinding != null && localVariableBinding.isValidBinding()) { |
| 883 |
finallyScope.shiftScopes[i] = localVariableBinding.declaringScope; |
| 884 |
} |
| 885 |
} |
| 886 |
finallyScope.shiftScopes[this.resources.length] = tryScope; |
| 887 |
} |
968 |
} |
| 888 |
} |
969 |
} |
| 889 |
this.tryBlock.resolveUsing(tryScope); |
970 |
this.tryBlock.resolveUsing(tryScope); |