javap/src/main/java/org/apidesign/javap/StackMapTableData.java
author Martin Soch <Martin.Soch@oracle.com>
Wed, 06 Feb 2013 17:03:26 +0100
brancharithmetic
changeset 689 f87c33d2fa7b
parent 281 f2352e0b713e
permissions -rw-r--r--
merge with trunk
     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 }