View | Details | Raw Unified | Return to bug 169017 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java (-9 / +58 lines)
Lines 38-43 Link Here
38
	
38
	
39
	public ArrayList variablesModificationsPositions;
39
	public ArrayList variablesModificationsPositions;
40
	
40
	
41
	public int[] stateIndexes;
42
	public int stateIndexesCounter;
43
	
41
public StackMapFrameCodeStream(ClassFile givenClassFile) {
44
public StackMapFrameCodeStream(ClassFile givenClassFile) {
42
	super(givenClassFile);
45
	super(givenClassFile);
43
}
46
}
Lines 56-66 Link Here
56
}
59
}
57
public void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
60
public void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
58
	// Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
61
	// Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
59
	for (int i = 0; i < visibleLocalsCount; i++) {
62
	loop: for (int i = 0; i < visibleLocalsCount; i++) {
60
		LocalVariableBinding localBinding = visibleLocals[i];
63
		LocalVariableBinding localBinding = visibleLocals[i];
61
		if (localBinding != null) {
64
		if (localBinding != null) {
62
			// Check if the local is definitely assigned
65
			// Check if the local is definitely assigned
63
			if (isDefinitelyAssigned(scope, initStateIndex, localBinding)) {
66
			boolean isDefinitelyAssigned = isDefinitelyAssigned(scope, initStateIndex, localBinding);
67
			if (!isDefinitelyAssigned) {
68
				if (this.stateIndexes != null) {
69
					for (int j = 0, max = this.stateIndexesCounter; j < max; j++) {
70
						if (isDefinitelyAssigned(scope, this.stateIndexes[j], localBinding)) {
71
							currentFrame.putLocal(localBinding.resolvedPosition, new VerificationTypeInfo(localBinding.type));
72
							if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) {
73
								/* There are two cases:
74
								 * 1) there is no initialization interval opened ==> add an opened interval
75
								 * 2) there is already some initialization intervals but the last one is closed ==> add an opened interval
76
								 * An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1]
77
								 * is equals to -1.
78
								 * initializationPCs is a collection of pairs of int:
79
								 * 	first value is the startPC and second value is the endPC. -1 one for the last value means that the interval
80
								 * 	is not closed yet.
81
								 */
82
								localBinding.recordInitializationStartPC(position);
83
							}
84
							continue loop;
85
						}
86
					}
87
				}
88
			} else {
89
				currentFrame.putLocal(localBinding.resolvedPosition, new VerificationTypeInfo(localBinding.type));
64
				if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) {
90
				if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) {
65
					/* There are two cases:
91
					/* There are two cases:
66
					 * 1) there is no initialization interval opened ==> add an opened interval
92
					 * 1) there is no initialization interval opened ==> add an opened interval
Lines 71-77 Link Here
71
					 * 	first value is the startPC and second value is the endPC. -1 one for the last value means that the interval
97
					 * 	first value is the startPC and second value is the endPC. -1 one for the last value means that the interval
72
					 * 	is not closed yet.
98
					 * 	is not closed yet.
73
					 */
99
					 */
74
					currentFrame.putLocal(localBinding.resolvedPosition, new VerificationTypeInfo(localBinding.type));
100
					localBinding.recordInitializationStartPC(position);
75
				}
101
				}
76
			}
102
			}
77
		}
103
		}
Lines 81-87 Link Here
81
		this.variablesModificationsPositions.add(newValue);
107
		this.variablesModificationsPositions.add(newValue);
82
	}
108
	}
83
	storeStackMapFrame();
109
	storeStackMapFrame();
84
	super.addDefinitelyAssignedVariables(scope, initStateIndex);
85
}
110
}
86
public void addVariable(LocalVariableBinding localBinding) {
111
public void addVariable(LocalVariableBinding localBinding) {
87
	currentFrame.putLocal(localBinding.resolvedPosition, new VerificationTypeInfo(localBinding.type));	
112
	currentFrame.putLocal(localBinding.resolvedPosition, new VerificationTypeInfo(localBinding.type));	
Lines 1746-1751 Link Here
1746
			this.currentFrame.numberOfStackItems -= 2;
1771
			this.currentFrame.numberOfStackItems -= 2;
1747
	}
1772
	}
1748
}
1773
}
1774
public void popStateIndex() {
1775
	this.stateIndexesCounter--;
1776
}
1749
public void pushOnStack(TypeBinding binding) {
1777
public void pushOnStack(TypeBinding binding) {
1750
	super.pushOnStack(binding);
1778
	super.pushOnStack(binding);
1751
	this.currentFrame.addStackItem(binding);
1779
	this.currentFrame.addStackItem(binding);
Lines 1754-1759 Link Here
1754
	super.putfield(fieldBinding);
1782
	super.putfield(fieldBinding);
1755
	this.currentFrame.numberOfStackItems -= 2;	
1783
	this.currentFrame.numberOfStackItems -= 2;	
1756
}
1784
}
1785
1786
public void pushStateIndex(int naturalExitMergeInitStateIndex) {
1787
	if (this.stateIndexes == null) {
1788
		this.stateIndexes = new int[3];
1789
	}
1790
	int length = this.stateIndexes.length;
1791
	if (length == this.stateIndexesCounter) {
1792
		// resize
1793
		System.arraycopy(this.stateIndexes, 0, (this.stateIndexes = new int[length * 2]), 0, length);
1794
	}
1795
	this.stateIndexes[this.stateIndexesCounter++] = naturalExitMergeInitStateIndex;
1796
}
1757
public void putstatic(FieldBinding fieldBinding) {
1797
public void putstatic(FieldBinding fieldBinding) {
1758
	super.putstatic(fieldBinding);
1798
	super.putstatic(fieldBinding);
1759
	this.currentFrame.numberOfStackItems--;	
1799
	this.currentFrame.numberOfStackItems--;	
Lines 1768-1778 Link Here
1768
}
1808
}
1769
public void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
1809
public void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
1770
	int index = this.visibleLocalsCount;
1810
	int index = this.visibleLocalsCount;
1771
	for (int i = 0; i < index; i++) {
1811
	loop : for (int i = 0; i < index; i++) {
1772
		LocalVariableBinding localBinding = visibleLocals[i];
1812
		LocalVariableBinding localBinding = visibleLocals[i];
1773
		if (localBinding != null && !isDefinitelyAssigned(scope, initStateIndex, localBinding)
1813
		if (localBinding != null && localBinding.initializationCount > 0) {
1774
				&& localBinding.initializationCount > 0) {
1814
			boolean isDefinitelyAssigned = isDefinitelyAssigned(scope, initStateIndex, localBinding);
1775
			this.currentFrame.removeLocals(localBinding.resolvedPosition);
1815
			if (!isDefinitelyAssigned) {
1816
				if (this.stateIndexes != null) {
1817
					for (int j = 0, max = this.stateIndexesCounter; j < max; j++) {
1818
						if (isDefinitelyAssigned(scope, this.stateIndexes[j], localBinding)) {
1819
							continue loop;
1820
						}
1821
					}
1822
				}
1823
				this.currentFrame.removeLocals(localBinding.resolvedPosition);
1824
				localBinding.recordInitializationEndPC(position);
1825
			}
1776
		}
1826
		}
1777
	}
1827
	}
1778
	Integer newValue = new Integer(this.position);
1828
	Integer newValue = new Integer(this.position);
Lines 1780-1786 Link Here
1780
		this.variablesModificationsPositions.add(newValue);
1830
		this.variablesModificationsPositions.add(newValue);
1781
	}
1831
	}
1782
	storeStackMapFrame();
1832
	storeStackMapFrame();
1783
	super.removeNotDefinitelyAssignedVariables(scope, initStateIndex);
1784
}
1833
}
1785
public void storeStackMapFrame() {
1834
public void storeStackMapFrame() {
1786
	int frameSize = this.frames.size();
1835
	int frameSize = this.frames.size();
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (-2 / +2 lines)
Lines 4525-4535 Link Here
4525
}
4525
}
4526
public boolean isDefinitelyAssigned(Scope scope, int initStateIndex, LocalVariableBinding local) {
4526
public boolean isDefinitelyAssigned(Scope scope, int initStateIndex, LocalVariableBinding local) {
4527
	// Mirror of UnconditionalFlowInfo.isDefinitelyAssigned(..)
4527
	// Mirror of UnconditionalFlowInfo.isDefinitelyAssigned(..)
4528
	if (initStateIndex == -1)
4529
		return false;
4530
	if ((local.tagBits & TagBits.IsArgument) != 0) {
4528
	if ((local.tagBits & TagBits.IsArgument) != 0) {
4531
		return true;
4529
		return true;
4532
	}
4530
	}
4531
	if (initStateIndex == -1)
4532
		return false;
4533
	int localPosition = local.id + maxFieldCount;
4533
	int localPosition = local.id + maxFieldCount;
4534
	MethodScope methodScope = scope.methodScope();
4534
	MethodScope methodScope = scope.methodScope();
4535
	// id is zero-based
4535
	// id is zero-based
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (-8 / +6 lines)
Lines 39-47 Link Here
39
39
40
	if (this.expression != null) {
40
	if (this.expression != null) {
41
		flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
41
		flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
42
		this.initStateIndex =
43
			currentScope.methodScope().recordInitializationStates(flowInfo);
44
	}
42
	}
43
	this.initStateIndex =
44
		currentScope.methodScope().recordInitializationStates(flowInfo);
45
	// compute the return sequence (running the finally blocks)
45
	// compute the return sequence (running the finally blocks)
46
	FlowContext traversedContext = flowContext;
46
	FlowContext traversedContext = flowContext;
47
	int subCount = 0;
47
	int subCount = 0;
Lines 132-143 Link Here
132
		Object reusableJSRTarget = this.expression == null ? (Object)TypeBinding.VOID : this.expression.reusableJSRTarget();
132
		Object reusableJSRTarget = this.expression == null ? (Object)TypeBinding.VOID : this.expression.reusableJSRTarget();
133
		for (int i = 0, max = this.subroutines.length; i < max; i++) {
133
		for (int i = 0, max = this.subroutines.length; i < max; i++) {
134
			SubRoutineStatement sub = this.subroutines[i];
134
			SubRoutineStatement sub = this.subroutines[i];
135
			boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, reusableJSRTarget);
135
			boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, reusableJSRTarget, this.initStateIndex, this.saveValueVariable);
136
			if (didEscape) {
136
			if (didEscape) {
137
					if (this.initStateIndex != -1) {
138
						codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
139
						codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
140
					}
141
					codeStream.recordPositionsFrom(pc, this.sourceStart);
137
					codeStream.recordPositionsFrom(pc, this.sourceStart);
142
					SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
138
					SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
143
					return;
139
					return;
Lines 174-180 Link Here
174
}
170
}
175
171
176
public void generateStoreSaveValueIfNecessary(CodeStream codeStream){
172
public void generateStoreSaveValueIfNecessary(CodeStream codeStream){
177
	if (this.saveValueVariable != null) codeStream.store(this.saveValueVariable, false);
173
	if (this.saveValueVariable != null) {
174
		codeStream.store(this.saveValueVariable, false);
175
	}
178
}
176
}
179
177
180
public boolean needValue() {
178
public boolean needValue() {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java (-1 / +1 lines)
Lines 45-51 Link Here
45
	if (this.subroutines != null){
45
	if (this.subroutines != null){
46
		for (int i = 0, max = this.subroutines.length; i < max; i++){
46
		for (int i = 0, max = this.subroutines.length; i < max; i++){
47
			SubRoutineStatement sub = this.subroutines[i];
47
			SubRoutineStatement sub = this.subroutines[i];
48
			boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, this.targetLabel);
48
			boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, this.targetLabel, this.initStateIndex, null);
49
			if (didEscape) {
49
			if (didEscape) {
50
					codeStream.recordPositionsFrom(pc, this.sourceStart);
50
					codeStream.recordPositionsFrom(pc, this.sourceStart);
51
					SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
51
					SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java (-1 / +2 lines)
Lines 13-18 Link Here
13
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
13
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
14
import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
15
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
15
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
16
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
16
17
17
/**
18
/**
18
 * Extra behavior for statements which are generating subroutines
19
 * Extra behavior for statements which are generating subroutines
Lines 55-61 Link Here
55
	}
56
	}
56
	
57
	
57
58
58
	public abstract boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation);	
59
	public abstract boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal);	
59
	
60
	
60
	public abstract boolean isSubRoutineEscaping();
61
	public abstract boolean isSubRoutineEscaping();
61
	
62
	
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java (-2 / +2 lines)
Lines 152-160 Link Here
152
}
152
}
153
153
154
/**
154
/**
155
 * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object)
155
 * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding)
156
 */
156
 */
157
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation) {
157
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) {
158
	codeStream.load(this.synchroVariable);
158
	codeStream.load(this.synchroVariable);
159
	codeStream.monitorexit();
159
	codeStream.monitorexit();
160
	exitAnyExceptionHandler();
160
	exitAnyExceptionHandler();
(-)compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-34 / +68 lines)
Lines 47-52 Link Here
47
	// for inlining/optimizing JSR instructions
47
	// for inlining/optimizing JSR instructions
48
	private Object[] reusableJSRTargets;
48
	private Object[] reusableJSRTargets;
49
	private BranchLabel[] reusableJSRSequenceStartLabels;
49
	private BranchLabel[] reusableJSRSequenceStartLabels;
50
	private int[] reusableJSRStateIndexes;
50
	private int reusableJSRTargetsCount = 0;
51
	private int reusableJSRTargetsCount = 0;
51
	
52
	
52
	private final static int NO_FINALLY = 0;										// no finally block
53
	private final static int NO_FINALLY = 0;										// no finally block
Lines 57-63 Link Here
57
	// for local variables table attributes
58
	// for local variables table attributes
58
	int mergedInitStateIndex = -1;
59
	int mergedInitStateIndex = -1;
59
	int preTryInitStateIndex = -1;
60
	int preTryInitStateIndex = -1;
60
	int postTryInitStateIndex = -1;
61
	int naturalExitMergeInitStateIndex = -1;
61
62
62
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
63
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
63
64
Lines 95-106 Link Here
95
		FlowInfo tryInfo;
96
		FlowInfo tryInfo;
96
		if (this.tryBlock.isEmptyBlock()) {
97
		if (this.tryBlock.isEmptyBlock()) {
97
			tryInfo = flowInfo;
98
			tryInfo = flowInfo;
98
			this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo);
99
		} else {
99
		} else {
100
			tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
100
			tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
101
			if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
101
			if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
102
				this.bits |= ASTNode.IsTryBlockExiting;
102
				this.bits |= ASTNode.IsTryBlockExiting;
103
			this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo);
104
		}
103
		}
105
104
106
		// check unreachable catch blocks
105
		// check unreachable catch blocks
Lines 207-218 Link Here
207
		FlowInfo tryInfo;
206
		FlowInfo tryInfo;
208
		if (this.tryBlock.isEmptyBlock()) {
207
		if (this.tryBlock.isEmptyBlock()) {
209
			tryInfo = flowInfo;
208
			tryInfo = flowInfo;
210
			this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo);
211
		} else {
209
		} else {
212
			tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
210
			tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
213
			if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
211
			if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
214
				this.bits |= ASTNode.IsTryBlockExiting;
212
				this.bits |= ASTNode.IsTryBlockExiting;
215
			this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo);
216
		}
213
		}
217
214
218
		// check unreachable catch blocks
215
		// check unreachable catch blocks
Lines 293-298 Link Here
293
			flowContext.initsOnFinally.add(handlingContext.initsOnFinally);
290
			flowContext.initsOnFinally.add(handlingContext.initsOnFinally);
294
		}
291
		}
295
292
293
		this.naturalExitMergeInitStateIndex =
294
			currentScope.methodScope().recordInitializationStates(tryInfo);
296
		if (subInfo == FlowInfo.DEAD_END) {
295
		if (subInfo == FlowInfo.DEAD_END) {
297
			this.mergedInitStateIndex =
296
			this.mergedInitStateIndex =
298
				currentScope.methodScope().recordInitializationStates(subInfo);
297
				currentScope.methodScope().recordInitializationStates(subInfo);
Lines 404-419 Link Here
404
				case FINALLY_SUBROUTINE :
403
				case FINALLY_SUBROUTINE :
405
				case FINALLY_INLINE :
404
				case FINALLY_INLINE :
406
					requiresNaturalExit = true;
405
					requiresNaturalExit = true;
407
					if (this.postTryInitStateIndex != -1) {
406
					if (this.naturalExitMergeInitStateIndex != -1) {
408
						codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
407
						codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
409
						codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
408
						codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
410
					}
409
					}
411
					codeStream.goto_(naturalExitLabel);
410
					codeStream.goto_(naturalExitLabel);
412
					break;
411
					break;
413
				case NO_FINALLY :
412
				case NO_FINALLY :
414
					if (this.postTryInitStateIndex != -1) {
413
					if (this.naturalExitMergeInitStateIndex != -1) {
415
						codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
414
						codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
416
						codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
415
						codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
417
					}
416
					}
418
					codeStream.goto_(naturalExitLabel);
417
					codeStream.goto_(naturalExitLabel);
419
					break;
418
					break;
Lines 464-472 Link Here
464
							requiresNaturalExit = true;
463
							requiresNaturalExit = true;
465
							// fall through
464
							// fall through
466
						case NO_FINALLY :
465
						case NO_FINALLY :
467
							if (this.postTryInitStateIndex != -1) {
466
							if (this.naturalExitMergeInitStateIndex != -1) {
468
								codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
467
								codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
469
								codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
468
								codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
470
							}
469
							}
471
							codeStream.goto_(naturalExitLabel);
470
							codeStream.goto_(naturalExitLabel);
472
							break;
471
							break;
Lines 491-496 Link Here
491
			if (this.preTryInitStateIndex != -1) {
490
			if (this.preTryInitStateIndex != -1) {
492
				// reset initialization state, as for a normal catch block
491
				// reset initialization state, as for a normal catch block
493
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex);
492
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex);
493
				codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex);
494
			}
494
			}
495
			this.placeAllAnyExceptionHandler();
495
			this.placeAllAnyExceptionHandler();
496
			if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place();
496
			if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place();
Lines 557-565 Link Here
557
						break;
557
						break;
558
					case FINALLY_INLINE :
558
					case FINALLY_INLINE :
559
						// inlined finally here can see all merged variables
559
						// inlined finally here can see all merged variables
560
						if (this.postTryInitStateIndex != -1) {
560
						boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream;
561
							codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
561
						if (isStackMapFrameCodeStream) {
562
							codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
562
							((StackMapFrameCodeStream) codeStream).pushStateIndex(this.naturalExitMergeInitStateIndex);
563
						}
564
						if (this.naturalExitMergeInitStateIndex != -1) {
565
							codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
566
							codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
563
						}
567
						}
564
						naturalExitLabel.place();
568
						naturalExitLabel.place();
565
						// entire sequence for finally is associated to finally block
569
						// entire sequence for finally is associated to finally block
Lines 572-577 Link Here
572
									position,
576
									position,
573
									this.finallyBlock.sourceEnd);
577
									this.finallyBlock.sourceEnd);
574
						}
578
						}
579
						if (isStackMapFrameCodeStream) {
580
							((StackMapFrameCodeStream) codeStream).popStateIndex();
581
						}
575
						break;
582
						break;
576
					case FINALLY_DOES_NOT_COMPLETE :
583
					case FINALLY_DOES_NOT_COMPLETE :
577
						break;
584
						break;
Lines 617-626 Link Here
617
}
624
}
618
625
619
/**
626
/**
620
 * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object)
627
 * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding)
621
 */
628
 */
622
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation) {
629
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) {
623
630
631
	boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream;
624
	int finallyMode = finallyMode();
632
	int finallyMode = finallyMode();
625
	switch(finallyMode) {
633
	switch(finallyMode) {
626
		case FINALLY_DOES_NOT_COMPLETE :
634
		case FINALLY_DOES_NOT_COMPLETE :
Lines 633-638 Link Here
633
	}
641
	}
634
	// optimize subroutine invocation sequences, using the targetLocation (if any)
642
	// optimize subroutine invocation sequences, using the targetLocation (if any)
635
	if (targetLocation != null) {
643
	if (targetLocation != null) {
644
		boolean reuseTargetLocation = true;
636
		if (this.reusableJSRTargetsCount > 0) {
645
		if (this.reusableJSRTargetsCount > 0) {
637
			nextReusableTarget: for (int i = 0, count = this.reusableJSRTargetsCount; i < count; i++) {
646
			nextReusableTarget: for (int i = 0, count = this.reusableJSRTargetsCount; i < count; i++) {
638
				Object reusableJSRTarget = this.reusableJSRTargets[i];
647
				Object reusableJSRTarget = this.reusableJSRTargets[i];
Lines 648-679 Link Here
648
					continue nextReusableTarget;
657
					continue nextReusableTarget;
649
				}
658
				}
650
				// current target has been used in the past, simply branch to its label
659
				// current target has been used in the past, simply branch to its label
651
				codeStream.goto_(this.reusableJSRSequenceStartLabels[i]);
660
				if ((this.reusableJSRStateIndexes[i] != stateIndex) && finallyMode == FINALLY_INLINE && isStackMapFrameCodeStream) {
652
				return true;
661
					reuseTargetLocation = false;
662
					break nextReusableTarget;
663
				} else {
664
					codeStream.goto_(this.reusableJSRSequenceStartLabels[i]);
665
					return true;
666
				}
653
			}
667
			}
654
		} else {
668
		} else {
655
			this.reusableJSRTargets = new Object[3];
669
			this.reusableJSRTargets = new Object[3];
656
			this.reusableJSRSequenceStartLabels = new BranchLabel[3];
670
			this.reusableJSRSequenceStartLabels = new BranchLabel[3];
671
			this.reusableJSRStateIndexes = new int[3];
672
		}
673
		if (reuseTargetLocation) {
674
			if (this.reusableJSRTargetsCount == this.reusableJSRTargets.length) {
675
				System.arraycopy(this.reusableJSRTargets, 0, this.reusableJSRTargets = new Object[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount);
676
				System.arraycopy(this.reusableJSRSequenceStartLabels, 0, this.reusableJSRSequenceStartLabels = new BranchLabel[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount);
677
				System.arraycopy(this.reusableJSRStateIndexes, 0, this.reusableJSRStateIndexes = new int[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount);
678
			}
679
			this.reusableJSRTargets[this.reusableJSRTargetsCount] = targetLocation;
680
			BranchLabel reusableJSRSequenceStartLabel = new BranchLabel(codeStream);
681
			reusableJSRSequenceStartLabel.place();
682
			this.reusableJSRStateIndexes[this.reusableJSRTargetsCount] = stateIndex;
683
			this.reusableJSRSequenceStartLabels[this.reusableJSRTargetsCount++] = reusableJSRSequenceStartLabel;
657
		}
684
		}
658
		if (this.reusableJSRTargetsCount == this.reusableJSRTargets.length) {
685
	}
659
			System.arraycopy(this.reusableJSRTargets, 0, this.reusableJSRTargets = new Object[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount);
660
			System.arraycopy(this.reusableJSRSequenceStartLabels, 0, this.reusableJSRSequenceStartLabels = new BranchLabel[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount);
661
		}
662
		this.reusableJSRTargets[this.reusableJSRTargetsCount] = targetLocation;
663
		BranchLabel reusableJSRSequenceStartLabel = new BranchLabel(codeStream);
664
		reusableJSRSequenceStartLabel.place();
665
		this.reusableJSRSequenceStartLabels[this.reusableJSRTargetsCount++] = reusableJSRSequenceStartLabel;
666
	}			
667
	if (finallyMode == FINALLY_INLINE) {
686
	if (finallyMode == FINALLY_INLINE) {
668
		if (this.preTryInitStateIndex != -1) {
687
		if (isStackMapFrameCodeStream) {
669
			// reset initialization state, as for a normal catch block
688
			((StackMapFrameCodeStream) codeStream).pushStateIndex(stateIndex);
670
			codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex);
689
			if (this.naturalExitMergeInitStateIndex != -1 || stateIndex != -1) {
690
				// reset initialization state, as for a normal catch block
691
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
692
				codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
693
			}
694
		} else {
695
			if (this.naturalExitMergeInitStateIndex != -1) {
696
				// reset initialization state, as for a normal catch block
697
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
698
				codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex);
699
			}
700
		}
701
		if (secretLocal != null) {
702
			codeStream.addVariable(secretLocal);
671
		}
703
		}
672
		// cannot use jsr bytecode, then simply inline the subroutine
704
		// 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
705
		// inside try block, ensure to deactivate all catch block exception handlers while inlining finally block
674
		exitAnyExceptionHandler();
706
		exitAnyExceptionHandler();
675
		exitDeclaredExceptionHandlers(codeStream);
707
		exitDeclaredExceptionHandlers(codeStream);
676
		this.finallyBlock.generateCode(currentScope, codeStream);
708
		this.finallyBlock.generateCode(currentScope, codeStream);
709
		if (isStackMapFrameCodeStream) {
710
			((StackMapFrameCodeStream) codeStream).popStateIndex();
711
		}
677
	} else {
712
	} else {
678
		// classic subroutine invocation, distinguish case of non-returning subroutine
713
		// classic subroutine invocation, distinguish case of non-returning subroutine
679
		codeStream.jsr(this.subRoutineStartLabel);
714
		codeStream.jsr(this.subRoutineStartLabel);
Lines 682-688 Link Here
682
	}
717
	}
683
	return false;
718
	return false;
684
}
719
}
685
686
public boolean isSubRoutineEscaping() {
720
public boolean isSubRoutineEscaping() {
687
	return (this.bits & ASTNode.IsSubRoutineEscaping) != 0;
721
	return (this.bits & ASTNode.IsSubRoutineEscaping) != 0;
688
}
722
}

Return to bug 169017