diff options
author | Olivier Thomann | 2019-02-11 23:29:59 +0000 |
---|---|---|
committer | Manoj Palat | 2019-02-12 01:52:25 +0000 |
commit | dd1ad840550c0405543b14b09d21f3c532e89227 (patch) | |
tree | 07638a9e73e90fcece61d72864ce54593d666777 | |
parent | 38aa04c36dd56e5b4177f0ccc5530d29f59a7341 (diff) | |
download | eclipse.jdt.core-dd1ad840550c0405543b14b09d21f3c532e89227.tar.gz eclipse.jdt.core-dd1ad840550c0405543b14b09d21f3c532e89227.tar.xz eclipse.jdt.core-dd1ad840550c0405543b14b09d21f3c532e89227.zip |
Bug 544298 [12][codegen] Switch Expressions - exceeded stack size
Change-Id: Ie88811808167dbcde8e7a2c4cdda5a6236fc601a
4 files changed, 64 insertions, 14 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java index 37e8abfa02..e3d78a2c57 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java @@ -1834,4 +1834,55 @@ public class SwitchExpressionTest extends AbstractRegressionTest { customOptions, new String[] {"--enable-preview"}); } + public void testBug544298() { + runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " enum MyEnum {\n" + + " FIRST;\n" + + " }\n" + + "\n" + + " public void foo(MyEnum myEnum) {\n" + + " int i = switch (myEnum) {\n" + + " case FIRST -> 1;\n" + + " };\n" + + " System.out.println( \"i:\" + i);\n" + + " }\n" + + "\n" + + " public static void main(String argv[]) {\n" + + " new X().foo(MyEnum.FIRST);\n" + + " }\n" + + "}" + }, + "i:1", + null, + new String[] {"--enable-preview"}); + } + public void testBug544298_2() { + runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " enum MyEnum {\n" + + " FIRST;\n" + + " }\n" + + "\n" + + " public void foo(MyEnum myEnum) {\n" + + " int i = switch (myEnum) {\n" + + " case FIRST -> 1;\n" + + " default -> 0;\n" + + " };\n" + + " System.out.println( \"i:\" + i);\n" + + " }\n" + + "\n" + + " public static void main(String argv[]) {\n" + + " new X().foo(MyEnum.FIRST);\n" + + " }\n" + + "}" + }, + "i:1", + null, + new String[] {"--enable-preview"}); + } }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java index cf2efddbf8..abfd06d9cc 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java @@ -355,11 +355,10 @@ public class SwitchStatement extends Expression { } if (this.expectedType() != null) { TypeBinding expectedType = this.expectedType().erasure(); - /* - * is the last goto was optimized the lastAbruptCompletion is equal to -1 which means there is already some value on the - * stack so we don't need to add one. - */ - codeStream.recordExpressionType(expectedType, codeStream.lastAbruptCompletion != -1 ? 1 : 0); + boolean optimizedGoto = codeStream.lastAbruptCompletion == -1; + // if the last bytecode was an optimized goto (value is already on the stack) or an enum switch without default case, then we need to adjust the + // stack depth to reflect the fact that there is an value on the stack (return type of the switch expression) + codeStream.recordExpressionType(expectedType, optimizedGoto ? 0 : 1, optimizedGoto); } codeStream.recordPositionsFrom(pc, this.sourceStart); } finally { @@ -481,7 +480,8 @@ public class SwitchStatement extends Expression { } } boolean enumInSwitchExpression = resolvedType1.isEnum() && this instanceof SwitchExpression; - if (this.defaultCase == null && enumInSwitchExpression) { + boolean isEnumSwitchWithoutDefaultCase = this.defaultCase == null && enumInSwitchExpression; + if (isEnumSwitchWithoutDefaultCase) { // we want to force an line number entry to get an end position after the switch statement if (this.preSwitchInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSwitchInitStateIndex); @@ -517,11 +517,10 @@ public class SwitchStatement extends Expression { } if (this.expectedType() != null) { TypeBinding expectedType = this.expectedType().erasure(); - /* - * is the last goto was optimized the lastAbruptCompletion is equal to -1 which means there is already some value on the - * stack so we don't need to add one. - */ - codeStream.recordExpressionType(expectedType, codeStream.lastAbruptCompletion != -1 ? 1 : 0); + boolean optimizedGoto = codeStream.lastAbruptCompletion == -1; + // if the last bytecode was an optimized goto (value is already on the stack) or an enum switch without default case, then we need to adjust the + // stack depth to reflect the fact that there is an value on the stack (return type of the switch expression) + codeStream.recordExpressionType(expectedType, optimizedGoto ? 0 : 1, optimizedGoto || isEnumSwitchWithoutDefaultCase); } codeStream.recordPositionsFrom(pc, this.sourceStart); } finally { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java index 18903e8156..5f4cc19307 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java @@ -6318,7 +6318,7 @@ public void record(LocalVariableBinding local) { public void recordExpressionType(TypeBinding typeBinding) { // nothing to do } -public void recordExpressionType(TypeBinding typeBinding, int delta) { +public void recordExpressionType(TypeBinding typeBinding, int delta, boolean adjustStackDepth) { // nothing to do } public void recordPositionsFrom(int startPC, int sourcePos) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java index b73023a00e..f49b793159 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java @@ -304,9 +304,9 @@ public void recordExpressionType(TypeBinding typeBinding) { addStackDepthMarker(this.position, 0, typeBinding); } @Override -public void recordExpressionType(TypeBinding typeBinding, int delta) { +public void recordExpressionType(TypeBinding typeBinding, int delta, boolean adjustStackDepth) { addStackDepthMarker(this.position, delta, typeBinding); - if (delta == 0) { + if (adjustStackDepth) { // optimized goto // the break label already adjusted the stack depth (-1 or -2 depending on the return type) // we need to adjust back to what it was |