|
Lines 28-34
Link Here
|
| 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$ |
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$; |
31 |
static final char[] SECRET_CAUGHT_THROWABLE_VARIABLE_NAME = " caughtThrowable".toCharArray(); //$NON-NLS-1$; |
| 32 |
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$ |
| 33 |
|
33 |
|
| 34 |
private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0]; |
34 |
private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0]; |
|
Lines 72-79
Link Here
|
| 72 |
int naturalExitMergeInitStateIndex = -1; |
72 |
int naturalExitMergeInitStateIndex = -1; |
| 73 |
int[] catchExitInitStateIndexes; |
73 |
int[] catchExitInitStateIndexes; |
| 74 |
private LocalVariableBinding primaryExceptionVariable; |
74 |
private LocalVariableBinding primaryExceptionVariable; |
| 75 |
private LocalVariableBinding temporaryThrowableVariable; |
75 |
private LocalVariableBinding caughtThrowableVariable; |
| 76 |
private ExceptionLabel[] resourceBlockLabels; |
76 |
private ExceptionLabel[] resourceExceptionLabels; |
| 77 |
|
77 |
|
| 78 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
78 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
| 79 |
|
79 |
|
|
Lines 93-100
Link Here
|
| 93 |
if (this.primaryExceptionVariable != null) { |
93 |
if (this.primaryExceptionVariable != null) { |
| 94 |
this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED; |
94 |
this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED; |
| 95 |
} |
95 |
} |
| 96 |
if (this.temporaryThrowableVariable != null) { |
96 |
if (this.caughtThrowableVariable != null) { |
| 97 |
this.temporaryThrowableVariable.useFlag = LocalVariableBinding.USED; |
97 |
this.caughtThrowableVariable.useFlag = LocalVariableBinding.USED; |
| 98 |
} |
98 |
} |
| 99 |
if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused |
99 |
if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused |
| 100 |
this.returnAddressVariable.useFlag = LocalVariableBinding.USED; |
100 |
this.returnAddressVariable.useFlag = LocalVariableBinding.USED; |
|
Lines 440-455
Link Here
|
| 440 |
this.declaredExceptionLabels = exceptionLabels; |
440 |
this.declaredExceptionLabels = exceptionLabels; |
| 441 |
int resourceCount = this.resources.length; |
441 |
int resourceCount = this.resources.length; |
| 442 |
if (resourceCount > 0) { |
442 |
if (resourceCount > 0) { |
| 443 |
this.resourceBlockLabels = new ExceptionLabel[resourceCount + 1]; |
443 |
this.resourceExceptionLabels = new ExceptionLabel[resourceCount + 1]; |
| 444 |
codeStream.aconst_null(); |
444 |
codeStream.aconst_null(); |
| 445 |
codeStream.store(this.primaryExceptionVariable, false /* value not required */); |
445 |
codeStream.store(this.primaryExceptionVariable, false /* value not required */); |
| 446 |
codeStream.addVariable(this.primaryExceptionVariable); |
446 |
codeStream.addVariable(this.primaryExceptionVariable); |
| 447 |
codeStream.aconst_null(); |
447 |
codeStream.aconst_null(); |
| 448 |
codeStream.store(this.temporaryThrowableVariable, false /* value not required */); |
448 |
codeStream.store(this.caughtThrowableVariable, false /* value not required */); |
| 449 |
codeStream.addVariable(this.temporaryThrowableVariable); |
449 |
codeStream.addVariable(this.caughtThrowableVariable); |
| 450 |
for (int i = 0; i <= resourceCount; i++) { |
450 |
for (int i = 0; i <= resourceCount; i++) { |
| 451 |
this.resourceBlockLabels[i] = new ExceptionLabel(codeStream, this.scope.getJavaLangThrowable()); |
451 |
this.resourceExceptionLabels[i] = new ExceptionLabel(codeStream, this.scope.getJavaLangThrowable()); |
| 452 |
this.resourceBlockLabels[i].placeStart(); |
452 |
this.resourceExceptionLabels[i].placeStart(); |
| 453 |
if (i < resourceCount) { |
453 |
if (i < resourceCount) { |
| 454 |
this.resources[i].generateCode(this.scope, codeStream); |
454 |
this.resources[i].generateCode(this.scope, codeStream); |
| 455 |
} |
455 |
} |
|
Lines 459-465
Link Here
|
| 459 |
if (resourceCount > 0) { |
459 |
if (resourceCount > 0) { |
| 460 |
for (int i = resourceCount; i >= 0; i--) { |
460 |
for (int i = resourceCount; i >= 0; i--) { |
| 461 |
BranchLabel exitLabel = new BranchLabel(codeStream); |
461 |
BranchLabel exitLabel = new BranchLabel(codeStream); |
| 462 |
this.resourceBlockLabels[i].placeEnd(); |
462 |
this.resourceExceptionLabels[i].placeEnd(); |
| 463 |
|
463 |
|
| 464 |
LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null; |
464 |
LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null; |
| 465 |
if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { |
465 |
if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { |
|
Lines 472-493
Link Here
|
| 472 |
codeStream.goto_(exitLabel); |
472 |
codeStream.goto_(exitLabel); |
| 473 |
} |
473 |
} |
| 474 |
codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); |
474 |
codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); |
| 475 |
this.resourceBlockLabels[i].place(); |
475 |
this.resourceExceptionLabels[i].place(); |
| 476 |
BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream); |
476 |
if (i == resourceCount) { |
| 477 |
codeStream.store(this.temporaryThrowableVariable, false); |
477 |
// inner most try's catch/finally can be a lot simpler. |
| 478 |
codeStream.load(this.primaryExceptionVariable); |
478 |
codeStream.store(this.primaryExceptionVariable, false); |
| 479 |
codeStream.ifnonnull(elseLabel); |
479 |
// fall through, invoke close() and re-throw. |
| 480 |
codeStream.load(this.temporaryThrowableVariable); |
480 |
} else { |
| 481 |
codeStream.store(this.primaryExceptionVariable, false); |
481 |
BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream); |
| 482 |
codeStream.goto_(postElseLabel); |
482 |
codeStream.store(this.caughtThrowableVariable, false); |
| 483 |
elseLabel.place(); |
483 |
codeStream.load(this.primaryExceptionVariable); |
| 484 |
codeStream.load(this.primaryExceptionVariable); |
484 |
codeStream.ifnonnull(elseLabel); |
| 485 |
codeStream.load(this.temporaryThrowableVariable); |
485 |
codeStream.load(this.caughtThrowableVariable); |
| 486 |
codeStream.if_acmpeq(postElseLabel); |
486 |
codeStream.store(this.primaryExceptionVariable, false); |
| 487 |
codeStream.load(this.primaryExceptionVariable); |
487 |
codeStream.goto_(postElseLabel); |
| 488 |
codeStream.load(this.temporaryThrowableVariable); |
488 |
elseLabel.place(); |
| 489 |
codeStream.invokeThrowableAddSuppressed(); |
489 |
codeStream.load(this.primaryExceptionVariable); |
| 490 |
postElseLabel.place(); |
490 |
codeStream.load(this.caughtThrowableVariable); |
|
|
491 |
codeStream.if_acmpeq(postElseLabel); |
| 492 |
codeStream.load(this.primaryExceptionVariable); |
| 493 |
codeStream.load(this.caughtThrowableVariable); |
| 494 |
codeStream.invokeThrowableAddSuppressed(); |
| 495 |
postElseLabel.place(); |
| 496 |
} |
| 491 |
if (i > 0) { |
497 |
if (i > 0) { |
| 492 |
// inline resource close here rather than bracketing the current catch block with a try region. |
498 |
// inline resource close here rather than bracketing the current catch block with a try region. |
| 493 |
BranchLabel postCloseLabel = new BranchLabel(codeStream); |
499 |
BranchLabel postCloseLabel = new BranchLabel(codeStream); |
|
Lines 503-509
Link Here
|
| 503 |
exitLabel.place(); |
509 |
exitLabel.place(); |
| 504 |
} |
510 |
} |
| 505 |
codeStream.removeVariable(this.primaryExceptionVariable); |
511 |
codeStream.removeVariable(this.primaryExceptionVariable); |
| 506 |
codeStream.removeVariable(this.temporaryThrowableVariable); |
512 |
codeStream.removeVariable(this.caughtThrowableVariable); |
| 507 |
} |
513 |
} |
| 508 |
} finally { |
514 |
} finally { |
| 509 |
this.declaredExceptionLabels = null; |
515 |
this.declaredExceptionLabels = null; |
|
Lines 755-760
Link Here
|
| 755 |
*/ |
761 |
*/ |
| 756 |
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { |
762 |
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { |
| 757 |
|
763 |
|
|
|
764 |
int resourceCount = this.resources.length; |
| 765 |
if (resourceCount > 0) { |
| 766 |
for (int i = resourceCount; i > 0; --i) { |
| 767 |
// disarm the handlers and take care of resource closure. |
| 768 |
this.resourceExceptionLabels[i].placeEnd(); |
| 769 |
LocalVariableBinding localVariable = this.resources[i-1].binding; |
| 770 |
BranchLabel exitLabel = new BranchLabel(codeStream); |
| 771 |
codeStream.load(localVariable); |
| 772 |
codeStream.ifnull(exitLabel); |
| 773 |
codeStream.load(localVariable); |
| 774 |
codeStream.invokeAutoCloseableClose(localVariable.type); |
| 775 |
exitLabel.place(); |
| 776 |
} |
| 777 |
// restore handlers |
| 778 |
for (int i = resourceCount; i > 0; --i) { |
| 779 |
this.resourceExceptionLabels[i].placeStart(); |
| 780 |
} |
| 781 |
} |
| 782 |
|
| 758 |
boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; |
783 |
boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; |
| 759 |
int finallyMode = finallyMode(); |
784 |
int finallyMode = finallyMode(); |
| 760 |
switch(finallyMode) { |
785 |
switch(finallyMode) { |
|
Lines 893-902
Link Here
|
| 893 |
new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); |
918 |
new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); |
| 894 |
resourceManagementScope.addLocalVariable(this.primaryExceptionVariable); |
919 |
resourceManagementScope.addLocalVariable(this.primaryExceptionVariable); |
| 895 |
this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable |
920 |
this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable |
| 896 |
this.temporaryThrowableVariable = |
921 |
this.caughtThrowableVariable = |
| 897 |
new LocalVariableBinding(TryStatement.SECRET_TEMPORARY_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); |
922 |
new LocalVariableBinding(TryStatement.SECRET_CAUGHT_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); |
| 898 |
resourceManagementScope.addLocalVariable(this.temporaryThrowableVariable); |
923 |
resourceManagementScope.addLocalVariable(this.caughtThrowableVariable); |
| 899 |
this.temporaryThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable |
924 |
this.caughtThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable |
| 900 |
} |
925 |
} |
| 901 |
for (int i = 0; i < resourceCount; i++) { |
926 |
for (int i = 0; i < resourceCount; i++) { |
| 902 |
this.resources[i].resolve(resourceManagementScope); |
927 |
this.resources[i].resolve(resourceManagementScope); |