javap/src/main/java/org/apidesign/javap/StackMapIterator.java
changeset 374 e5b4bd29f268
parent 281 f2352e0b713e
child 472 1a73c6e08cc5
     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	Mon Dec 24 07:57:33 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  }