rt/javap/src/main/java/org/apidesign/javap/StackMapIterator.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 472 javap/src/main/java/org/apidesign/javap/StackMapIterator.java@1a73c6e08cc5
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
lubomir@221
     1
/*
lubomir@221
     2
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
lubomir@221
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
lubomir@221
     4
 *
lubomir@221
     5
 * This code is free software; you can redistribute it and/or modify it
lubomir@221
     6
 * under the terms of the GNU General Public License version 2 only, as
lubomir@221
     7
 * published by the Free Software Foundation.  Oracle designates this
lubomir@221
     8
 * particular file as subject to the "Classpath" exception as provided
lubomir@221
     9
 * by Oracle in the LICENSE file that accompanied this code.
lubomir@221
    10
 *
lubomir@221
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
lubomir@221
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
lubomir@221
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
lubomir@221
    14
 * version 2 for more details (a copy is included in the LICENSE file that
lubomir@221
    15
 * accompanied this code).
lubomir@221
    16
 *
lubomir@221
    17
 * You should have received a copy of the GNU General Public License version
lubomir@221
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
lubomir@221
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
lubomir@221
    20
 *
lubomir@221
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
lubomir@221
    22
 * or visit www.oracle.com if you need additional information or have any
lubomir@221
    23
 * questions.
lubomir@221
    24
 */
lubomir@221
    25
lubomir@221
    26
package org.apidesign.javap;
lubomir@221
    27
lubomir@307
    28
import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
lubomir@307
    29
import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
lubomir@307
    30
import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
lubomir@307
    31
import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
lubomir@307
    32
import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
lubomir@307
    33
lubomir@221
    34
public final class StackMapIterator {
lubomir@221
    35
    private final StackMapTableData[] stackMapTable;
lubomir@307
    36
    private final TypeArray argTypes;
lubomir@281
    37
    private final TypeArray localTypes;
lubomir@281
    38
    private final TypeArray stackTypes;
lubomir@221
    39
lubomir@221
    40
    private int nextFrameIndex;
lubomir@221
    41
    private int lastFrameByteCodeOffset;
lubomir@221
    42
lubomir@221
    43
    private int byteCodeOffset;
lubomir@221
    44
lubomir@307
    45
    StackMapIterator(final MethodData methodData) {
lubomir@307
    46
        this(methodData.getStackMapTable(),
lubomir@307
    47
             methodData.getInternalSig(),
lubomir@307
    48
             methodData.isStatic());
lubomir@307
    49
    }
lubomir@307
    50
lubomir@307
    51
    StackMapIterator(final StackMapTableData[] stackMapTable,
lubomir@307
    52
                     final String methodSignature,
lubomir@307
    53
                     final boolean isStaticMethod) {
lubomir@221
    54
        this.stackMapTable = (stackMapTable != null)
lubomir@221
    55
                                 ? stackMapTable
lubomir@221
    56
                                 : new StackMapTableData[0];
lubomir@281
    57
lubomir@307
    58
        argTypes = getArgTypes(methodSignature, isStaticMethod);
lubomir@281
    59
        localTypes = new TypeArray();
lubomir@281
    60
        stackTypes = new TypeArray();
lubomir@307
    61
lubomir@307
    62
        localTypes.addAll(argTypes);
lubomir@307
    63
lubomir@281
    64
        lastFrameByteCodeOffset = -1;
lubomir@221
    65
        advanceBy(0);
lubomir@221
    66
    }
lubomir@221
    67
lubomir@221
    68
    public String getFrameAsString() {
lubomir@307
    69
        return (nextFrameIndex == 0)
lubomir@307
    70
                   ? StackMapTableData.toString("INITIAL", 0, null, null)
lubomir@307
    71
                   : stackMapTable[nextFrameIndex - 1].toString();
lubomir@221
    72
    }
lubomir@221
    73
lubomir@221
    74
    public int getFrameIndex() {
lubomir@221
    75
        return nextFrameIndex;
lubomir@221
    76
    }
lubomir@221
    77
lubomir@281
    78
    public TypeArray getFrameStack() {
lubomir@281
    79
        return stackTypes;
lubomir@221
    80
    }
lubomir@221
    81
lubomir@307
    82
    public TypeArray getFrameLocals() {
lubomir@307
    83
        return localTypes;
lubomir@307
    84
    }
lubomir@307
    85
lubomir@307
    86
    public TypeArray getArguments() {
lubomir@307
    87
        return argTypes;
lubomir@307
    88
    }
lubomir@307
    89
lubomir@221
    90
    public void advanceBy(final int numByteCodes) {
lubomir@221
    91
        if (numByteCodes < 0) {
lubomir@221
    92
            throw new IllegalStateException("Forward only iterator");
lubomir@221
    93
        }
lubomir@221
    94
lubomir@221
    95
        byteCodeOffset += numByteCodes;
lubomir@221
    96
        while ((nextFrameIndex < stackMapTable.length)
lubomir@221
    97
                    && ((byteCodeOffset - lastFrameByteCodeOffset)
lubomir@221
    98
                            >= (stackMapTable[nextFrameIndex].offsetDelta
lubomir@221
    99
                                    + 1))) {
lubomir@281
   100
            final StackMapTableData nextFrame = stackMapTable[nextFrameIndex];
lubomir@281
   101
lubomir@281
   102
            lastFrameByteCodeOffset += nextFrame.offsetDelta + 1;
lubomir@281
   103
            nextFrame.applyTo(localTypes, stackTypes);
lubomir@281
   104
lubomir@221
   105
            ++nextFrameIndex;
lubomir@221
   106
        }
lubomir@221
   107
    }
lubomir@221
   108
lubomir@221
   109
    public void advanceTo(final int nextByteCodeOffset) {
lubomir@221
   110
        advanceBy(nextByteCodeOffset - byteCodeOffset);
lubomir@221
   111
    }
lubomir@221
   112
lubomir@307
   113
    private static TypeArray getArgTypes(final String methodSignature,
lubomir@307
   114
                                         final boolean isStaticMethod) {
lubomir@307
   115
        final TypeArray argTypes = new TypeArray();
lubomir@307
   116
lubomir@307
   117
        if (!isStaticMethod) {
lubomir@307
   118
            argTypes.add(ITEM_Object);
lubomir@307
   119
        }
lubomir@307
   120
lubomir@307
   121
        if (methodSignature.charAt(0) != '(') {
lubomir@307
   122
            throw new IllegalArgumentException("Invalid method signature");
lubomir@307
   123
        }
lubomir@307
   124
lubomir@307
   125
        final int length = methodSignature.length();
lubomir@472
   126
        boolean skipType = false;
lubomir@307
   127
        int argType;
lubomir@307
   128
        for (int i = 1; i < length; ++i) {
lubomir@307
   129
            switch (methodSignature.charAt(i)) {
lubomir@307
   130
                case 'B':
lubomir@307
   131
                case 'C':
lubomir@307
   132
                case 'S':
lubomir@307
   133
                case 'Z':
lubomir@307
   134
                case 'I':
lubomir@307
   135
                    argType = ITEM_Integer;
lubomir@307
   136
                    break;
lubomir@307
   137
                case 'J':
lubomir@307
   138
                    argType = ITEM_Long;
lubomir@307
   139
                    break;
lubomir@307
   140
                case 'F':
lubomir@307
   141
                    argType = ITEM_Float;
lubomir@307
   142
                    break;
lubomir@307
   143
                case 'D':
lubomir@307
   144
                    argType = ITEM_Double;
lubomir@307
   145
                    break;
lubomir@307
   146
                case 'L': {
lubomir@307
   147
                    i = methodSignature.indexOf(';', i + 1);
lubomir@307
   148
                    if (i == -1) {
lubomir@307
   149
                        throw new IllegalArgumentException(
lubomir@307
   150
                                      "Invalid method signature");
lubomir@307
   151
                    }
lubomir@307
   152
                    argType = ITEM_Object;
lubomir@307
   153
                    break;
lubomir@307
   154
                }
lubomir@307
   155
                case ')':
lubomir@307
   156
                    // not interested in the return value type
lubomir@307
   157
                    return argTypes;
lubomir@307
   158
                case '[':
lubomir@472
   159
                    if (!skipType) {
lubomir@307
   160
                        argTypes.add(ITEM_Object);
lubomir@472
   161
                        skipType = true;
lubomir@307
   162
                    }
lubomir@307
   163
                    continue;
lubomir@307
   164
lubomir@307
   165
                default:
lubomir@307
   166
                    throw new IllegalArgumentException(
lubomir@307
   167
                                  "Invalid method signature");
lubomir@307
   168
            }
lubomir@307
   169
lubomir@472
   170
            if (!skipType) {
lubomir@307
   171
                argTypes.add(argType);
lubomir@307
   172
            } else {
lubomir@472
   173
                skipType = false;
lubomir@307
   174
            }
lubomir@307
   175
        }
lubomir@307
   176
lubomir@307
   177
        return argTypes;
lubomir@221
   178
    }
lubomir@221
   179
}