javap/src/main/java/org/apidesign/javap/StackMapTableData.java
author Lubomir Nerad <lubomir.nerad@oracle.com>
Fri, 07 Dec 2012 19:16:21 +0100
branchregisters
changeset 283 51043a802035
parent 221 3ee23267706c
child 307 eaf4e8387065
permissions -rw-r--r--
Using format string for code generation
     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             appendType(sb, types[0]);
    70             for (int i = 1; i < types.length; ++i) {
    71                 sb.append(", ");
    72                 appendType(sb, types[i]);
    73             }
    74         }
    75         sb.append(']');
    76     }
    77 
    78     private static void appendType(final StringBuilder sb, final int type) {
    79         switch (type & 0xff) {
    80             case ITEM_Bogus:
    81                 sb.append("_top_");
    82                 break;
    83             case ITEM_Integer:
    84                 sb.append("_int_");
    85                 break;
    86             case ITEM_Float:
    87                 sb.append("_float_");
    88                 break;
    89             case ITEM_Double:
    90                 sb.append("_double_");
    91                 break;
    92             case ITEM_Long:
    93                 sb.append("_long_");
    94                 break;
    95             case ITEM_Null:
    96                 sb.append("_null_");
    97                 break;
    98             case ITEM_InitObject: // UninitializedThis
    99                 sb.append("_init_");
   100                 break;
   101             case ITEM_Object:
   102                 sb.append("_object_");
   103                 break;
   104             case ITEM_NewObject: // Uninitialized
   105                 sb.append("_new_");
   106                 break;
   107             default:
   108                 sb.append("_unknown_");
   109                 break;
   110         }
   111     }
   112 
   113     static class SameFrame extends StackMapTableData {
   114         SameFrame(int frameType, int offsetDelta) {
   115             super(frameType);
   116             this.offsetDelta = offsetDelta;
   117         }
   118 
   119         @Override
   120         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   121             stackTypes.clear();
   122         }
   123 
   124         @Override
   125         public String toString() {
   126             return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
   127                                           ? "_FRAME_EXTENDED" : ""),
   128                             offsetDelta,
   129                             null, null);
   130         }
   131     }
   132 
   133     static class SameLocals1StackItem extends StackMapTableData {
   134         final int[] stack;
   135         SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) {
   136             super(frameType);
   137             this.offsetDelta = offsetDelta;
   138             this.stack = stack;
   139         }
   140 
   141         @Override
   142         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   143             stackTypes.setAll(stack);
   144         }
   145 
   146         @Override
   147         public String toString() {
   148             return toString(
   149                        "SAME_LOCALS_1_STACK_ITEM"
   150                            + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
   151                                   ? "_EXTENDED" : ""),
   152                        offsetDelta,
   153                        null, stack);
   154         }
   155     }
   156 
   157     static class ChopFrame extends StackMapTableData {
   158         ChopFrame(int frameType, int offsetDelta) {
   159             super(frameType);
   160             this.offsetDelta = offsetDelta;
   161         }
   162 
   163         @Override
   164         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   165             localTypes.setSize(localTypes.getSize()
   166                                    - (SAME_FRAME_EXTENDED - frameType));
   167             stackTypes.clear();
   168         }
   169 
   170         @Override
   171         public String toString() {
   172             return toString("CHOP", offsetDelta, null, null);
   173         }
   174     }
   175 
   176     static class AppendFrame extends StackMapTableData {
   177         final int[] locals;
   178         AppendFrame(int frameType, int offsetDelta, int[] locals) {
   179             super(frameType);
   180             this.offsetDelta = offsetDelta;
   181             this.locals = locals;
   182         }
   183 
   184         @Override
   185         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   186             localTypes.addAll(locals);
   187             stackTypes.clear();
   188         }
   189 
   190         @Override
   191         public String toString() {
   192             return toString("APPEND", offsetDelta, locals, null);
   193         }
   194     }
   195 
   196     static class FullFrame extends StackMapTableData {
   197         final int[] locals;
   198         final int[] stack;
   199         FullFrame(int offsetDelta, int[] locals, int[] stack) {
   200             super(FULL_FRAME);
   201             this.offsetDelta = offsetDelta;
   202             this.locals = locals;
   203             this.stack = stack;
   204         }
   205 
   206         @Override
   207         void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   208             localTypes.setAll(locals);
   209             stackTypes.setAll(stack);
   210         }
   211 
   212         @Override
   213         public String toString() {
   214             return toString("FULL", offsetDelta, locals, stack);
   215         }
   216     }
   217 
   218     static StackMapTableData getInstance(DataInputStream in, MethodData method)
   219                   throws IOException {
   220         int frameType = in.readUnsignedByte();
   221 
   222         if (frameType < SAME_FRAME_BOUND) {
   223             // same_frame
   224             return new SameFrame(frameType, frameType);
   225         } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) {
   226             // same_locals_1_stack_item_frame
   227             // read additional single stack element
   228             return new SameLocals1StackItem(frameType,
   229                                             (frameType - SAME_FRAME_BOUND),
   230                                             StackMapData.readTypeArray(in, 1, method));
   231         } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
   232             // same_locals_1_stack_item_extended
   233             return new SameLocals1StackItem(frameType,
   234                                             in.readUnsignedShort(),
   235                                             StackMapData.readTypeArray(in, 1, method));
   236         } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType  && frameType < SAME_FRAME_EXTENDED) {
   237             // chop_frame or same_frame_extended
   238             return new ChopFrame(frameType, in.readUnsignedShort());
   239         } else if (frameType == SAME_FRAME_EXTENDED) {
   240             // chop_frame or same_frame_extended
   241             return new SameFrame(frameType, in.readUnsignedShort());
   242         } else if (SAME_FRAME_EXTENDED < frameType  && frameType < FULL_FRAME) {
   243             // append_frame
   244             return new AppendFrame(frameType, in.readUnsignedShort(),
   245                                    StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method));
   246         } else if (frameType == FULL_FRAME) {
   247             // full_frame
   248             int offsetDelta = in.readUnsignedShort();
   249             int locals_size = in.readUnsignedShort();
   250             int[] locals = StackMapData.readTypeArray(in, locals_size, method);
   251             int stack_size = in.readUnsignedShort();
   252             int[] stack = StackMapData.readTypeArray(in, stack_size, method);
   253             return new FullFrame(offsetDelta, locals, stack);
   254         } else {
   255             throw new ClassFormatError("unrecognized frame_type in StackMapTable");
   256         }
   257     }
   258 }