javap/src/main/java/org/apidesign/javap/StackMapTableData.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
parent 281 f2352e0b713e
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
     1 /*
     2  * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 
    27 package org.apidesign.javap;
    28 
    29 import java.io.*;
    30 
    31 import static org.apidesign.javap.RuntimeConstants.*;
    32 
    33 /* represents one entry of StackMapTable attribute
    34  */
    35 abstract class StackMapTableData {
    36     final int frameType;
    37     int offsetDelta;
    38 
    39     StackMapTableData(int frameType) {
    40         this.frameType = frameType;
    41     }
    42 
    43     abstract void applyTo(TypeArray localTypes, TypeArray stackTypes);
    44 
    45     protected static String toString(
    46             final String frameType,
    47             final int offset,
    48             final int[] localTypes,
    49             final int[] stackTypes) {
    50         final StringBuilder sb = new StringBuilder(frameType);
    51 
    52         sb.append("(off: +").append(offset);
    53         if (localTypes != null) {
    54             sb.append(", locals: ");
    55             appendTypes(sb, localTypes);
    56         }
    57         if (stackTypes != null) {
    58             sb.append(", stack: ");
    59             appendTypes(sb, stackTypes);
    60         }
    61         sb.append(')');
    62 
    63         return sb.toString();
    64     }
    65 
    66     private static void appendTypes(final StringBuilder sb, final int[] types) {
    67         sb.append('[');
    68         if (types.length > 0) {
    69             sb.append(TypeArray.typeString(types[0]));
    70             for (int i = 1; i < types.length; ++i) {
    71                 sb.append(", ");
    72                 sb.append(TypeArray.typeString(types[i]));
    73             }
    74         }
    75         sb.append(']');
    76     }
    77 
    78     static class SameFrame extends StackMapTableData {
    79         SameFrame(int frameType, int offsetDelta) {
    80             super(frameType);
    81             this.offsetDelta = offsetDelta;
    82         }
    83 
    84         @Override
    85         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
    86             stackTypes.clear();
    87         }
    88 
    89         @Override
    90         public String toString() {
    91             return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
    92                                           ? "_FRAME_EXTENDED" : ""),
    93                             offsetDelta,
    94                             null, null);
    95         }
    96     }
    97 
    98     static class SameLocals1StackItem extends StackMapTableData {
    99         final int[] stack;
   100         SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) {
   101             super(frameType);
   102             this.offsetDelta = offsetDelta;
   103             this.stack = stack;
   104         }
   105 
   106         @Override
   107         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   108             stackTypes.setAll(stack);
   109         }
   110 
   111         @Override
   112         public String toString() {
   113             return toString(
   114                        "SAME_LOCALS_1_STACK_ITEM"
   115                            + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
   116                                   ? "_EXTENDED" : ""),
   117                        offsetDelta,
   118                        null, stack);
   119         }
   120     }
   121 
   122     static class ChopFrame extends StackMapTableData {
   123         ChopFrame(int frameType, int offsetDelta) {
   124             super(frameType);
   125             this.offsetDelta = offsetDelta;
   126         }
   127 
   128         @Override
   129         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   130             localTypes.setSize(localTypes.getSize()
   131                                    - (SAME_FRAME_EXTENDED - frameType));
   132             stackTypes.clear();
   133         }
   134 
   135         @Override
   136         public String toString() {
   137             return toString("CHOP", offsetDelta, null, null);
   138         }
   139     }
   140 
   141     static class AppendFrame extends StackMapTableData {
   142         final int[] locals;
   143         AppendFrame(int frameType, int offsetDelta, int[] locals) {
   144             super(frameType);
   145             this.offsetDelta = offsetDelta;
   146             this.locals = locals;
   147         }
   148 
   149         @Override
   150         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   151             localTypes.addAll(locals);
   152             stackTypes.clear();
   153         }
   154 
   155         @Override
   156         public String toString() {
   157             return toString("APPEND", offsetDelta, locals, null);
   158         }
   159     }
   160 
   161     static class FullFrame extends StackMapTableData {
   162         final int[] locals;
   163         final int[] stack;
   164         FullFrame(int offsetDelta, int[] locals, int[] stack) {
   165             super(FULL_FRAME);
   166             this.offsetDelta = offsetDelta;
   167             this.locals = locals;
   168             this.stack = stack;
   169         }
   170 
   171         @Override
   172         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   173             localTypes.setAll(locals);
   174             stackTypes.setAll(stack);
   175         }
   176 
   177         @Override
   178         public String toString() {
   179             return toString("FULL", offsetDelta, locals, stack);
   180         }
   181     }
   182 
   183     static StackMapTableData getInstance(DataInputStream in, MethodData method)
   184                   throws IOException {
   185         int frameType = in.readUnsignedByte();
   186 
   187         if (frameType < SAME_FRAME_BOUND) {
   188             // same_frame
   189             return new SameFrame(frameType, frameType);
   190         } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) {
   191             // same_locals_1_stack_item_frame
   192             // read additional single stack element
   193             return new SameLocals1StackItem(frameType,
   194                                             (frameType - SAME_FRAME_BOUND),
   195                                             StackMapData.readTypeArray(in, 1, method));
   196         } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
   197             // same_locals_1_stack_item_extended
   198             return new SameLocals1StackItem(frameType,
   199                                             in.readUnsignedShort(),
   200                                             StackMapData.readTypeArray(in, 1, method));
   201         } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType  && frameType < SAME_FRAME_EXTENDED) {
   202             // chop_frame or same_frame_extended
   203             return new ChopFrame(frameType, in.readUnsignedShort());
   204         } else if (frameType == SAME_FRAME_EXTENDED) {
   205             // chop_frame or same_frame_extended
   206             return new SameFrame(frameType, in.readUnsignedShort());
   207         } else if (SAME_FRAME_EXTENDED < frameType  && frameType < FULL_FRAME) {
   208             // append_frame
   209             return new AppendFrame(frameType, in.readUnsignedShort(),
   210                                    StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method));
   211         } else if (frameType == FULL_FRAME) {
   212             // full_frame
   213             int offsetDelta = in.readUnsignedShort();
   214             int locals_size = in.readUnsignedShort();
   215             int[] locals = StackMapData.readTypeArray(in, locals_size, method);
   216             int stack_size = in.readUnsignedShort();
   217             int[] stack = StackMapData.readTypeArray(in, stack_size, method);
   218             return new FullFrame(offsetDelta, locals, stack);
   219         } else {
   220             throw new ClassFormatError("unrecognized frame_type in StackMapTable");
   221         }
   222     }
   223 }