Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Thomann2012-09-26 08:29:51 +0000
committerJayaprakash Arthanareeswaran2012-10-19 04:49:05 +0000
commita00bb5eefc5dc1b2770154375a5f65dad7ebaf03 (patch)
tree3dc087e61562f5201d56fb2bf3f1fb8ffa7009ef
parent99610839b414c1a151891246c04d5389bbb2fe00 (diff)
downloadeclipse.jdt.core-a00bb5eefc5dc1b2770154375a5f65dad7ebaf03.tar.gz
eclipse.jdt.core-a00bb5eefc5dc1b2770154375a5f65dad7ebaf03.tar.xz
eclipse.jdt.core-a00bb5eefc5dc1b2770154375a5f65dad7ebaf03.zip
Fix for bug 385593: [compiler] Unexpected stackmap frames
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java108
2 files changed, 88 insertions, 23 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
index e50b97dbbf..2e5452338f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
@@ -1162,12 +1162,11 @@ public class StackMapAttributeTest extends AbstractRegressionTest {
" [pc: 19, pc: 102] local: x index: 1 type: X\n" +
" [pc: 2, pc: 111] local: i index: 2 type: int\n" +
" [pc: 90, pc: 102] local: diff index: 3 type: java.lang.Object\n" +
- " Stack map table: number of frames 8\n" +
+ " Stack map table: number of frames 7\n" +
" [pc: 5, full, stack: {}, locals: {java.lang.String[], _, int}]\n" +
" [pc: 38, full, stack: {}, locals: {java.lang.String[], X, int}]\n" +
" [pc: 44, same]\n" +
" [pc: 64, same]\n" +
- " [pc: 82, same]\n" +
" [pc: 85, same]\n" +
" [pc: 102, full, stack: {}, locals: {java.lang.String[], _, int}]\n" +
" [pc: 105, same]\n";
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index b2b2f9c87f..14dfa14df3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -18,8 +18,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
@@ -3191,9 +3194,9 @@ public class ClassFile implements TypeConstants, TypeIds {
StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
stackMapFrameCodeStream.removeFramePosition(code_length);
if (stackMapFrameCodeStream.hasFramePositions()) {
- ArrayList frames = new ArrayList();
- traverse(isClinit ? null : methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit);
- int numberOfFrames = frames.size();
+ Map frames = new HashMap();
+ List realFrames = traverse(isClinit ? null : methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit);
+ int numberOfFrames = realFrames.size();
if (numberOfFrames > 1) {
int stackMapTableAttributeOffset = localContentsOffset;
// add the stack map table attribute
@@ -3216,10 +3219,10 @@ public class ClassFile implements TypeConstants, TypeIds {
if (localContentsOffset + 2 >= this.contents.length) {
resizeContents(2);
}
- StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
+ StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0);
for (int j = 1; j < numberOfFrames; j++) {
// select next frame
- currentFrame = (StackMapFrame) frames.get(j);
+ currentFrame = (StackMapFrame) realFrames.get(j);
// generate current frame
// need to find differences between the current frame and the previous frame
int frameOffset = currentFrame.pc;
@@ -3368,9 +3371,9 @@ public class ClassFile implements TypeConstants, TypeIds {
StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
stackMapFrameCodeStream.removeFramePosition(code_length);
if (stackMapFrameCodeStream.hasFramePositions()) {
- ArrayList frames = new ArrayList();
- traverse(isClinit ? null: methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit);
- int numberOfFrames = frames.size();
+ Map frames = new HashMap();
+ List realFrames = traverse(isClinit ? null: methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit);
+ int numberOfFrames = realFrames.size();
if (numberOfFrames > 1) {
int stackMapTableAttributeOffset = localContentsOffset;
// add the stack map table attribute
@@ -3393,12 +3396,12 @@ public class ClassFile implements TypeConstants, TypeIds {
if (localContentsOffset + 2 >= this.contents.length) {
resizeContents(2);
}
- StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
+ StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0);
StackMapFrame prevFrame = null;
for (int j = 1; j < numberOfFrames; j++) {
// select next frame
prevFrame = currentFrame;
- currentFrame = (StackMapFrame) frames.get(j);
+ currentFrame = (StackMapFrame) realFrames.get(j);
// generate current frame
// need to find differences between the current frame and the previous frame
int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
@@ -3835,7 +3838,6 @@ public class ClassFile implements TypeConstants, TypeIds {
methodSignature.length);
}
-
private final int i4At(byte[] reference, int relativeOffset,
int structOffset) {
int position = relativeOffset + structOffset;
@@ -4244,8 +4246,32 @@ public class ClassFile implements TypeConstants, TypeIds {
this.methodCountOffset = this.contentsOffset;
this.contentsOffset += 2;
}
+
+ private List filterFakeFrames(Set realJumpTargets, Map frames, int codeLength) {
+ // no more frame to generate
+ // filter out "fake" frames
+ realJumpTargets.remove(new Integer(codeLength));
+ List result = new ArrayList();
+ for (Iterator iterator = realJumpTargets.iterator(); iterator.hasNext(); ) {
+ Integer jumpTarget = (Integer) iterator.next();
+ StackMapFrame frame = (StackMapFrame) frames.get(jumpTarget);
+ if (frame != null) {
+ result.add(frame);
+ }
+ }
+ Collections.sort(result, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ StackMapFrame frame = (StackMapFrame) o1;
+ StackMapFrame frame2 = (StackMapFrame) o2;
+ return frame.pc - frame2.pc;
+ }
+ });
+ return result;
+ }
+
+ public List traverse(MethodBinding methodBinding, int maxLocals, byte[] bytecodes, int codeOffset, int codeLength, Map frames, boolean isClinit) {
+ Set realJumpTarget = new HashSet();
- public void traverse(MethodBinding methodBinding, int maxLocals, byte[] bytecodes, int codeOffset, int codeLength, ArrayList frames, boolean isClinit) {
StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
int[] framePositions = stackMapFrameCodeStream.getFramePositions();
int pc = codeOffset;
@@ -4293,7 +4319,14 @@ public class ClassFile implements TypeConstants, TypeIds {
initializeDefaultLocals(frame, methodBinding, maxLocals, codeLength);
}
frame.pc = -1;
- frames.add(frame.duplicate());
+ add(frames, frame.duplicate());
+ addRealJumpTarget(realJumpTarget, -1);
+ for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
+ ExceptionLabel exceptionLabel = this.codeStream.exceptionLabels[i];
+ if (exceptionLabel != null) {
+ addRealJumpTarget(realJumpTarget, exceptionLabel.position);
+ }
+ }
while (true) {
int currentPC = pc - codeOffset;
if (hasStackMarkers && stackMarker.pc == currentPC) {
@@ -4346,8 +4379,7 @@ public class ClassFile implements TypeConstants, TypeIds {
if (indexInFramePositions < framePositionsLength) {
currentFramePosition = framePositions[indexInFramePositions];
} else {
- // no more frame to generate
- return;
+ currentFramePosition = Integer.MAX_VALUE;
}
} while (currentFramePosition < currentPC);
}
@@ -4358,13 +4390,12 @@ public class ClassFile implements TypeConstants, TypeIds {
// initialize locals
initializeLocals(isClinit ? true : methodBinding.isStatic(), currentPC, currentFrame);
// insert a new frame
- frames.add(currentFrame);
+ add(frames, currentFrame);
indexInFramePositions++;
if (indexInFramePositions < framePositionsLength) {
currentFramePosition = framePositions[indexInFramePositions];
} else {
- // no more frame to generate
- return;
+ currentFramePosition = Integer.MAX_VALUE;
}
}
byte opcode = (byte) u1At(bytecodes, 0, pc);
@@ -4910,6 +4941,7 @@ public class ClassFile implements TypeConstants, TypeIds {
case Opcodes.OPC_ifgt:
case Opcodes.OPC_ifle:
frame.numberOfStackItems--;
+ addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
pc += 3;
break;
case Opcodes.OPC_if_icmpeq:
@@ -4921,23 +4953,32 @@ public class ClassFile implements TypeConstants, TypeIds {
case Opcodes.OPC_if_acmpeq:
case Opcodes.OPC_if_acmpne:
frame.numberOfStackItems -= 2;
+ addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
pc += 3;
break;
case Opcodes.OPC_goto:
+ addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
pc += 3;
+ addRealJumpTarget(realJumpTarget, pc - codeOffset);
break;
case Opcodes.OPC_tableswitch:
pc++;
while (((pc - codeOffset) & 0x03) != 0) {
pc++;
}
+ // default offset
+ addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
pc += 4; // default
int low = i4At(bytecodes, 0, pc);
pc += 4;
int high = i4At(bytecodes, 0, pc);
pc += 4;
int length = high - low + 1;
- pc += (length * 4);
+ for (int i = 0; i < length; i++) {
+ // pair offset
+ addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+ pc += 4;
+ }
frame.numberOfStackItems--;
break;
case Opcodes.OPC_lookupswitch:
@@ -4945,9 +4986,16 @@ public class ClassFile implements TypeConstants, TypeIds {
while (((pc - codeOffset) & 0x03) != 0) {
pc++;
}
- pc += 4; // default
+ addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+ pc += 4; // default offset
int npairs = (int) u4At(bytecodes, 0, pc);
- pc += (4 + npairs * 8);
+ pc += 4; // npair value
+ for (int i = 0; i < npairs; i++) {
+ pc += 4; // case value
+ // pair offset
+ addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+ pc += 4;
+ }
frame.numberOfStackItems--;
break;
case Opcodes.OPC_ireturn:
@@ -4957,9 +5005,11 @@ public class ClassFile implements TypeConstants, TypeIds {
case Opcodes.OPC_areturn:
frame.numberOfStackItems--;
pc++;
+ addRealJumpTarget(realJumpTarget, pc - codeOffset);
break;
case Opcodes.OPC_return:
pc++;
+ addRealJumpTarget(realJumpTarget, pc - codeOffset);
break;
case Opcodes.OPC_getstatic:
index = u2At(bytecodes, 1, pc);
@@ -5362,6 +5412,7 @@ public class ClassFile implements TypeConstants, TypeIds {
case Opcodes.OPC_athrow:
frame.numberOfStackItems--;
pc++;
+ addRealJumpTarget(realJumpTarget, pc - codeOffset);
break;
case Opcodes.OPC_checkcast:
index = u2At(bytecodes, 1, pc);
@@ -5456,10 +5507,13 @@ public class ClassFile implements TypeConstants, TypeIds {
case Opcodes.OPC_ifnull:
case Opcodes.OPC_ifnonnull:
frame.numberOfStackItems--;
+ addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
pc += 3;
break;
case Opcodes.OPC_goto_w:
+ addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 1, pc));
pc += 5;
+ addRealJumpTarget(realJumpTarget, pc - codeOffset); // handle infinite loop
break;
default: // should not occur
this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
@@ -5477,8 +5531,15 @@ public class ClassFile implements TypeConstants, TypeIds {
break;
}
}
+ return filterFakeFrames(realJumpTarget, frames, codeLength);
}
+ private void addRealJumpTarget(Set realJumpTarget, int pc) {
+ realJumpTarget.add(new Integer(pc));
+ }
+ private void add(Map frames, StackMapFrame frame) {
+ frames.put(new Integer(frame.pc), frame);
+ }
private final int u1At(byte[] reference, int relativeOffset,
int structOffset) {
return (reference[relativeOffset + structOffset] & 0xFF);
@@ -5499,6 +5560,11 @@ public class ClassFile implements TypeConstants, TypeIds {
+ ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF));
}
+ private final int i2At(byte[] reference, int relativeOffset, int structOffset) {
+ int position = relativeOffset + structOffset;
+ return (reference[position++] << 8) + (reference[position] & 0xFF);
+ }
+
public char[] utf8At(byte[] reference, int absoluteOffset,
int bytesAvailable) {
int length = bytesAvailable;

Back to the top