1.1 --- a/javap/src/main/java/org/apidesign/javap/StackMapIterator.java Fri Dec 07 15:02:35 2012 +0100
1.2 +++ b/javap/src/main/java/org/apidesign/javap/StackMapIterator.java Wed Dec 12 11:04:02 2012 +0100
1.3 @@ -25,23 +25,15 @@
1.4
1.5 package org.apidesign.javap;
1.6
1.7 +import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
1.8 +import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
1.9 +import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
1.10 +import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
1.11 +import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
1.12 +
1.13 public final class StackMapIterator {
1.14 - private static final StackMapTableData INITIAL_FRAME =
1.15 - new StackMapTableData(-1) {
1.16 - @Override
1.17 - void applyTo(TypeArray localTypes, TypeArray stackTypes) {
1.18 - localTypes.clear();
1.19 - stackTypes.clear();
1.20 - }
1.21 -
1.22 - @Override
1.23 - public String toString() {
1.24 - return toString("INITIAL", 0, null, null);
1.25 - }
1.26 -
1.27 - };
1.28 -
1.29 private final StackMapTableData[] stackMapTable;
1.30 + private final TypeArray argTypes;
1.31 private final TypeArray localTypes;
1.32 private final TypeArray stackTypes;
1.33
1.34 @@ -50,19 +42,33 @@
1.35
1.36 private int byteCodeOffset;
1.37
1.38 - StackMapIterator(final StackMapTableData[] stackMapTable) {
1.39 + StackMapIterator(final MethodData methodData) {
1.40 + this(methodData.getStackMapTable(),
1.41 + methodData.getInternalSig(),
1.42 + methodData.isStatic());
1.43 + }
1.44 +
1.45 + StackMapIterator(final StackMapTableData[] stackMapTable,
1.46 + final String methodSignature,
1.47 + final boolean isStaticMethod) {
1.48 this.stackMapTable = (stackMapTable != null)
1.49 ? stackMapTable
1.50 : new StackMapTableData[0];
1.51
1.52 + argTypes = getArgTypes(methodSignature, isStaticMethod);
1.53 localTypes = new TypeArray();
1.54 stackTypes = new TypeArray();
1.55 +
1.56 + localTypes.addAll(argTypes);
1.57 +
1.58 lastFrameByteCodeOffset = -1;
1.59 advanceBy(0);
1.60 }
1.61
1.62 public String getFrameAsString() {
1.63 - return getCurrentFrame().toString();
1.64 + return (nextFrameIndex == 0)
1.65 + ? StackMapTableData.toString("INITIAL", 0, null, null)
1.66 + : stackMapTable[nextFrameIndex - 1].toString();
1.67 }
1.68
1.69 public int getFrameIndex() {
1.70 @@ -73,6 +79,14 @@
1.71 return stackTypes;
1.72 }
1.73
1.74 + public TypeArray getFrameLocals() {
1.75 + return localTypes;
1.76 + }
1.77 +
1.78 + public TypeArray getArguments() {
1.79 + return argTypes;
1.80 + }
1.81 +
1.82 public void advanceBy(final int numByteCodes) {
1.83 if (numByteCodes < 0) {
1.84 throw new IllegalStateException("Forward only iterator");
1.85 @@ -96,9 +110,70 @@
1.86 advanceBy(nextByteCodeOffset - byteCodeOffset);
1.87 }
1.88
1.89 - private StackMapTableData getCurrentFrame() {
1.90 - return (nextFrameIndex == 0)
1.91 - ? INITIAL_FRAME
1.92 - : stackMapTable[nextFrameIndex - 1];
1.93 + private static TypeArray getArgTypes(final String methodSignature,
1.94 + final boolean isStaticMethod) {
1.95 + final TypeArray argTypes = new TypeArray();
1.96 +
1.97 + if (!isStaticMethod) {
1.98 + argTypes.add(ITEM_Object);
1.99 + }
1.100 +
1.101 + if (methodSignature.charAt(0) != '(') {
1.102 + throw new IllegalArgumentException("Invalid method signature");
1.103 + }
1.104 +
1.105 + final int length = methodSignature.length();
1.106 + int skipType = 0;
1.107 + int argType;
1.108 + for (int i = 1; i < length; ++i) {
1.109 + switch (methodSignature.charAt(i)) {
1.110 + case 'B':
1.111 + case 'C':
1.112 + case 'S':
1.113 + case 'Z':
1.114 + case 'I':
1.115 + argType = ITEM_Integer;
1.116 + break;
1.117 + case 'J':
1.118 + argType = ITEM_Long;
1.119 + break;
1.120 + case 'F':
1.121 + argType = ITEM_Float;
1.122 + break;
1.123 + case 'D':
1.124 + argType = ITEM_Double;
1.125 + break;
1.126 + case 'L': {
1.127 + i = methodSignature.indexOf(';', i + 1);
1.128 + if (i == -1) {
1.129 + throw new IllegalArgumentException(
1.130 + "Invalid method signature");
1.131 + }
1.132 + argType = ITEM_Object;
1.133 + break;
1.134 + }
1.135 + case ')':
1.136 + // not interested in the return value type
1.137 + return argTypes;
1.138 + case '[':
1.139 + if (skipType == 0) {
1.140 + argTypes.add(ITEM_Object);
1.141 + }
1.142 + ++skipType;
1.143 + continue;
1.144 +
1.145 + default:
1.146 + throw new IllegalArgumentException(
1.147 + "Invalid method signature");
1.148 + }
1.149 +
1.150 + if (skipType == 0) {
1.151 + argTypes.add(argType);
1.152 + } else {
1.153 + --skipType;
1.154 + }
1.155 + }
1.156 +
1.157 + return argTypes;
1.158 }
1.159 }