Lines 57-63
Link Here
|
57 |
// for local variables table attributes |
57 |
// for local variables table attributes |
58 |
int mergedInitStateIndex = -1; |
58 |
int mergedInitStateIndex = -1; |
59 |
int preTryInitStateIndex = -1; |
59 |
int preTryInitStateIndex = -1; |
60 |
int postTryInitStateIndex = -1; |
60 |
int naturalExitMergeInitStateIndex = -1; |
61 |
|
61 |
|
62 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
62 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
63 |
|
63 |
|
Lines 95-106
Link Here
|
95 |
FlowInfo tryInfo; |
95 |
FlowInfo tryInfo; |
96 |
if (this.tryBlock.isEmptyBlock()) { |
96 |
if (this.tryBlock.isEmptyBlock()) { |
97 |
tryInfo = flowInfo; |
97 |
tryInfo = flowInfo; |
98 |
this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); |
|
|
99 |
} else { |
98 |
} else { |
100 |
tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy()); |
99 |
tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy()); |
101 |
if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0) |
100 |
if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0) |
102 |
this.bits |= ASTNode.IsTryBlockExiting; |
101 |
this.bits |= ASTNode.IsTryBlockExiting; |
103 |
this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); |
|
|
104 |
} |
102 |
} |
105 |
|
103 |
|
106 |
// check unreachable catch blocks |
104 |
// check unreachable catch blocks |
Lines 207-218
Link Here
|
207 |
FlowInfo tryInfo; |
205 |
FlowInfo tryInfo; |
208 |
if (this.tryBlock.isEmptyBlock()) { |
206 |
if (this.tryBlock.isEmptyBlock()) { |
209 |
tryInfo = flowInfo; |
207 |
tryInfo = flowInfo; |
210 |
this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); |
|
|
211 |
} else { |
208 |
} else { |
212 |
tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy()); |
209 |
tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy()); |
213 |
if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0) |
210 |
if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0) |
214 |
this.bits |= ASTNode.IsTryBlockExiting; |
211 |
this.bits |= ASTNode.IsTryBlockExiting; |
215 |
this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); |
|
|
216 |
} |
212 |
} |
217 |
|
213 |
|
218 |
// check unreachable catch blocks |
214 |
// check unreachable catch blocks |
Lines 298-303
Link Here
|
298 |
currentScope.methodScope().recordInitializationStates(subInfo); |
294 |
currentScope.methodScope().recordInitializationStates(subInfo); |
299 |
return subInfo; |
295 |
return subInfo; |
300 |
} else { |
296 |
} else { |
|
|
297 |
this.naturalExitMergeInitStateIndex = |
298 |
currentScope.methodScope().recordInitializationStates(tryInfo); |
301 |
FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo); |
299 |
FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo); |
302 |
this.mergedInitStateIndex = |
300 |
this.mergedInitStateIndex = |
303 |
currentScope.methodScope().recordInitializationStates(mergedInfo); |
301 |
currentScope.methodScope().recordInitializationStates(mergedInfo); |
Lines 404-419
Link Here
|
404 |
case FINALLY_SUBROUTINE : |
402 |
case FINALLY_SUBROUTINE : |
405 |
case FINALLY_INLINE : |
403 |
case FINALLY_INLINE : |
406 |
requiresNaturalExit = true; |
404 |
requiresNaturalExit = true; |
407 |
if (this.postTryInitStateIndex != -1) { |
405 |
if (this.naturalExitMergeInitStateIndex != -1) { |
408 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
406 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
409 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
407 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
410 |
} |
408 |
} |
411 |
codeStream.goto_(naturalExitLabel); |
409 |
codeStream.goto_(naturalExitLabel); |
412 |
break; |
410 |
break; |
413 |
case NO_FINALLY : |
411 |
case NO_FINALLY : |
414 |
if (this.postTryInitStateIndex != -1) { |
412 |
if (this.naturalExitMergeInitStateIndex != -1) { |
415 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
413 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
416 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
414 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
417 |
} |
415 |
} |
418 |
codeStream.goto_(naturalExitLabel); |
416 |
codeStream.goto_(naturalExitLabel); |
419 |
break; |
417 |
break; |
Lines 464-472
Link Here
|
464 |
requiresNaturalExit = true; |
462 |
requiresNaturalExit = true; |
465 |
// fall through |
463 |
// fall through |
466 |
case NO_FINALLY : |
464 |
case NO_FINALLY : |
467 |
if (this.postTryInitStateIndex != -1) { |
465 |
if (this.naturalExitMergeInitStateIndex != -1) { |
468 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
466 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
469 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
467 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
470 |
} |
468 |
} |
471 |
codeStream.goto_(naturalExitLabel); |
469 |
codeStream.goto_(naturalExitLabel); |
472 |
break; |
470 |
break; |
Lines 491-496
Link Here
|
491 |
if (this.preTryInitStateIndex != -1) { |
489 |
if (this.preTryInitStateIndex != -1) { |
492 |
// reset initialization state, as for a normal catch block |
490 |
// reset initialization state, as for a normal catch block |
493 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); |
491 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); |
|
|
492 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); |
494 |
} |
493 |
} |
495 |
this.placeAllAnyExceptionHandler(); |
494 |
this.placeAllAnyExceptionHandler(); |
496 |
if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place(); |
495 |
if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place(); |
Lines 557-565
Link Here
|
557 |
break; |
556 |
break; |
558 |
case FINALLY_INLINE : |
557 |
case FINALLY_INLINE : |
559 |
// inlined finally here can see all merged variables |
558 |
// inlined finally here can see all merged variables |
560 |
if (this.postTryInitStateIndex != -1) { |
559 |
boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; |
561 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
560 |
if (isStackMapFrameCodeStream) { |
562 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); |
561 |
((StackMapFrameCodeStream) codeStream).pushStateIndex(this.naturalExitMergeInitStateIndex); |
|
|
562 |
} |
563 |
if (this.naturalExitMergeInitStateIndex != -1) { |
564 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
565 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
563 |
} |
566 |
} |
564 |
naturalExitLabel.place(); |
567 |
naturalExitLabel.place(); |
565 |
// entire sequence for finally is associated to finally block |
568 |
// entire sequence for finally is associated to finally block |
Lines 572-577
Link Here
|
572 |
position, |
575 |
position, |
573 |
this.finallyBlock.sourceEnd); |
576 |
this.finallyBlock.sourceEnd); |
574 |
} |
577 |
} |
|
|
578 |
if (isStackMapFrameCodeStream) { |
579 |
((StackMapFrameCodeStream) codeStream).popStateIndex(); |
580 |
} |
575 |
break; |
581 |
break; |
576 |
case FINALLY_DOES_NOT_COMPLETE : |
582 |
case FINALLY_DOES_NOT_COMPLETE : |
577 |
break; |
583 |
break; |
Lines 617-625
Link Here
|
617 |
} |
623 |
} |
618 |
|
624 |
|
619 |
/** |
625 |
/** |
620 |
* @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object) |
626 |
* @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding) |
621 |
*/ |
627 |
*/ |
622 |
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation) { |
628 |
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { |
623 |
|
629 |
|
624 |
int finallyMode = finallyMode(); |
630 |
int finallyMode = finallyMode(); |
625 |
switch(finallyMode) { |
631 |
switch(finallyMode) { |
Lines 663-679
Link Here
|
663 |
BranchLabel reusableJSRSequenceStartLabel = new BranchLabel(codeStream); |
669 |
BranchLabel reusableJSRSequenceStartLabel = new BranchLabel(codeStream); |
664 |
reusableJSRSequenceStartLabel.place(); |
670 |
reusableJSRSequenceStartLabel.place(); |
665 |
this.reusableJSRSequenceStartLabels[this.reusableJSRTargetsCount++] = reusableJSRSequenceStartLabel; |
671 |
this.reusableJSRSequenceStartLabels[this.reusableJSRTargetsCount++] = reusableJSRSequenceStartLabel; |
666 |
} |
672 |
} |
667 |
if (finallyMode == FINALLY_INLINE) { |
673 |
if (finallyMode == FINALLY_INLINE) { |
668 |
if (this.preTryInitStateIndex != -1) { |
674 |
boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; |
|
|
675 |
if (isStackMapFrameCodeStream) { |
676 |
((StackMapFrameCodeStream) codeStream).pushStateIndex(stateIndex); |
677 |
} |
678 |
if (this.naturalExitMergeInitStateIndex != -1 || stateIndex != -1) { |
669 |
// reset initialization state, as for a normal catch block |
679 |
// reset initialization state, as for a normal catch block |
670 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); |
680 |
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
|
|
681 |
codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); |
682 |
} |
683 |
if (secretLocal != null) { |
684 |
codeStream.addVariable(secretLocal); |
671 |
} |
685 |
} |
672 |
// cannot use jsr bytecode, then simply inline the subroutine |
686 |
// cannot use jsr bytecode, then simply inline the subroutine |
673 |
// inside try block, ensure to deactivate all catch block exception handlers while inlining finally block |
687 |
// inside try block, ensure to deactivate all catch block exception handlers while inlining finally block |
674 |
exitAnyExceptionHandler(); |
688 |
exitAnyExceptionHandler(); |
675 |
exitDeclaredExceptionHandlers(codeStream); |
689 |
exitDeclaredExceptionHandlers(codeStream); |
676 |
this.finallyBlock.generateCode(currentScope, codeStream); |
690 |
this.finallyBlock.generateCode(currentScope, codeStream); |
|
|
691 |
if (isStackMapFrameCodeStream) { |
692 |
((StackMapFrameCodeStream) codeStream).popStateIndex(); |
693 |
} |
677 |
} else { |
694 |
} else { |
678 |
// classic subroutine invocation, distinguish case of non-returning subroutine |
695 |
// classic subroutine invocation, distinguish case of non-returning subroutine |
679 |
codeStream.jsr(this.subRoutineStartLabel); |
696 |
codeStream.jsr(this.subRoutineStartLabel); |
Lines 682-688
Link Here
|
682 |
} |
699 |
} |
683 |
return false; |
700 |
return false; |
684 |
} |
701 |
} |
685 |
|
|
|
686 |
public boolean isSubRoutineEscaping() { |
702 |
public boolean isSubRoutineEscaping() { |
687 |
return (this.bits & ASTNode.IsSubRoutineEscaping) != 0; |
703 |
return (this.bits & ASTNode.IsSubRoutineEscaping) != 0; |
688 |
} |
704 |
} |