langtools/src/jdk.compiler/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java
changeset 30846 2b3f379840f0
parent 30845 43ddd58a5a56
child 30847 9385b9c8506b
equal deleted inserted replaced
30845:43ddd58a5a56 30846:2b3f379840f0
     1 /*
       
     2  * Copyright (c) 2007, 2009, 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 package com.sun.tools.classfile;
       
    27 
       
    28 import java.io.IOException;
       
    29 
       
    30 /**
       
    31  * See JVMS, section 4.8.4.
       
    32  *
       
    33  *  <p><b>This is NOT part of any supported API.
       
    34  *  If you write code that depends on this, you do so at your own risk.
       
    35  *  This code and its internal interfaces are subject to change or
       
    36  *  deletion without notice.</b>
       
    37  */
       
    38 public class StackMapTable_attribute extends Attribute {
       
    39     static class InvalidStackMap extends AttributeException {
       
    40         private static final long serialVersionUID = -5659038410855089780L;
       
    41         InvalidStackMap(String msg) {
       
    42             super(msg);
       
    43         }
       
    44     }
       
    45 
       
    46     StackMapTable_attribute(ClassReader cr, int name_index, int length)
       
    47             throws IOException, InvalidStackMap {
       
    48         super(name_index, length);
       
    49         number_of_entries = cr.readUnsignedShort();
       
    50         entries = new stack_map_frame[number_of_entries];
       
    51         for (int i = 0; i < number_of_entries; i++)
       
    52             entries[i] = stack_map_frame.read(cr);
       
    53     }
       
    54 
       
    55     public StackMapTable_attribute(ConstantPool constant_pool, stack_map_frame[] entries)
       
    56             throws ConstantPoolException {
       
    57         this(constant_pool.getUTF8Index(Attribute.StackMapTable), entries);
       
    58     }
       
    59 
       
    60     public StackMapTable_attribute(int name_index, stack_map_frame[] entries) {
       
    61         super(name_index, length(entries));
       
    62         this.number_of_entries = entries.length;
       
    63         this.entries = entries;
       
    64     }
       
    65 
       
    66     public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
    67         return visitor.visitStackMapTable(this, data);
       
    68     }
       
    69 
       
    70     static int length(stack_map_frame[] entries) {
       
    71         int n = 2;
       
    72         for (stack_map_frame entry: entries)
       
    73             n += entry.length();
       
    74         return n;
       
    75     }
       
    76 
       
    77     public final int number_of_entries;
       
    78     public final stack_map_frame entries[];
       
    79 
       
    80     public static abstract class stack_map_frame {
       
    81         static stack_map_frame read(ClassReader cr)
       
    82                 throws IOException, InvalidStackMap {
       
    83             int frame_type = cr.readUnsignedByte();
       
    84             if (frame_type <= 63)
       
    85                 return new same_frame(frame_type);
       
    86             else if (frame_type <= 127)
       
    87                 return new same_locals_1_stack_item_frame(frame_type, cr);
       
    88             else if (frame_type <= 246)
       
    89                 throw new Error("unknown frame_type " + frame_type);
       
    90             else if (frame_type == 247)
       
    91                 return new same_locals_1_stack_item_frame_extended(frame_type, cr);
       
    92             else if (frame_type <= 250)
       
    93                 return new chop_frame(frame_type, cr);
       
    94             else if (frame_type == 251)
       
    95                 return new same_frame_extended(frame_type, cr);
       
    96             else if (frame_type <= 254)
       
    97                 return new append_frame(frame_type, cr);
       
    98             else
       
    99                 return new full_frame(frame_type, cr);
       
   100         }
       
   101 
       
   102         protected stack_map_frame(int frame_type) {
       
   103             this.frame_type = frame_type;
       
   104         }
       
   105 
       
   106         public int length() {
       
   107             return 1;
       
   108         }
       
   109 
       
   110         public abstract int getOffsetDelta();
       
   111 
       
   112         public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
       
   113 
       
   114         public final int frame_type;
       
   115 
       
   116         public static interface Visitor<R,P> {
       
   117             R visit_same_frame(same_frame frame, P p);
       
   118             R visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, P p);
       
   119             R visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, P p);
       
   120             R visit_chop_frame(chop_frame frame, P p);
       
   121             R visit_same_frame_extended(same_frame_extended frame, P p);
       
   122             R visit_append_frame(append_frame frame, P p);
       
   123             R visit_full_frame(full_frame frame, P p);
       
   124         }
       
   125     }
       
   126 
       
   127     public static class same_frame extends stack_map_frame {
       
   128         same_frame(int frame_type) {
       
   129             super(frame_type);
       
   130         }
       
   131 
       
   132         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   133             return visitor.visit_same_frame(this, data);
       
   134         }
       
   135 
       
   136         public int getOffsetDelta() {
       
   137             return frame_type;
       
   138         }
       
   139     }
       
   140 
       
   141     public static class same_locals_1_stack_item_frame extends stack_map_frame {
       
   142         same_locals_1_stack_item_frame(int frame_type, ClassReader cr)
       
   143                 throws IOException, InvalidStackMap {
       
   144             super(frame_type);
       
   145             stack = new verification_type_info[1];
       
   146             stack[0] = verification_type_info.read(cr);
       
   147         }
       
   148 
       
   149         @Override
       
   150         public int length() {
       
   151             return super.length() + stack[0].length();
       
   152         }
       
   153 
       
   154         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   155             return visitor.visit_same_locals_1_stack_item_frame(this, data);
       
   156         }
       
   157 
       
   158         public int getOffsetDelta() {
       
   159             return frame_type - 64;
       
   160         }
       
   161 
       
   162         public final verification_type_info[] stack;
       
   163     }
       
   164 
       
   165     public static class same_locals_1_stack_item_frame_extended extends stack_map_frame {
       
   166         same_locals_1_stack_item_frame_extended(int frame_type, ClassReader cr)
       
   167                 throws IOException, InvalidStackMap {
       
   168             super(frame_type);
       
   169             offset_delta = cr.readUnsignedShort();
       
   170             stack = new verification_type_info[1];
       
   171             stack[0] = verification_type_info.read(cr);
       
   172         }
       
   173 
       
   174         @Override
       
   175         public int length() {
       
   176             return super.length() + 2 + stack[0].length();
       
   177         }
       
   178 
       
   179         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   180             return visitor.visit_same_locals_1_stack_item_frame_extended(this, data);
       
   181         }
       
   182 
       
   183         public int getOffsetDelta() {
       
   184             return offset_delta;
       
   185         }
       
   186 
       
   187         public final int offset_delta;
       
   188         public final verification_type_info[] stack;
       
   189     }
       
   190 
       
   191     public static class chop_frame extends stack_map_frame {
       
   192         chop_frame(int frame_type, ClassReader cr) throws IOException {
       
   193             super(frame_type);
       
   194             offset_delta = cr.readUnsignedShort();
       
   195         }
       
   196 
       
   197         @Override
       
   198         public int length() {
       
   199             return super.length() + 2;
       
   200         }
       
   201 
       
   202         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   203             return visitor.visit_chop_frame(this, data);
       
   204         }
       
   205 
       
   206         public int getOffsetDelta() {
       
   207             return offset_delta;
       
   208         }
       
   209 
       
   210         public final int offset_delta;
       
   211     }
       
   212 
       
   213     public static class same_frame_extended extends stack_map_frame {
       
   214         same_frame_extended(int frame_type, ClassReader cr) throws IOException {
       
   215             super(frame_type);
       
   216             offset_delta = cr.readUnsignedShort();
       
   217         }
       
   218 
       
   219         @Override
       
   220         public int length() {
       
   221             return super.length() + 2;
       
   222         }
       
   223 
       
   224         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   225             return visitor.visit_same_frame_extended(this, data);
       
   226         }
       
   227 
       
   228         public int getOffsetDelta() {
       
   229             return offset_delta;
       
   230         }
       
   231 
       
   232         public final int offset_delta;
       
   233     }
       
   234 
       
   235     public static class append_frame extends stack_map_frame {
       
   236         append_frame(int frame_type, ClassReader cr)
       
   237                 throws IOException, InvalidStackMap {
       
   238             super(frame_type);
       
   239             offset_delta = cr.readUnsignedShort();
       
   240             locals = new verification_type_info[frame_type - 251];
       
   241             for (int i = 0; i < locals.length; i++)
       
   242                 locals[i] = verification_type_info.read(cr);
       
   243         }
       
   244 
       
   245         @Override
       
   246         public int length() {
       
   247             int n = super.length() + 2;
       
   248             for (verification_type_info local: locals)
       
   249                 n += local.length();
       
   250             return n;
       
   251         }
       
   252 
       
   253         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   254             return visitor.visit_append_frame(this, data);
       
   255         }
       
   256 
       
   257         public int getOffsetDelta() {
       
   258             return offset_delta;
       
   259         }
       
   260 
       
   261         public final int offset_delta;
       
   262         public final verification_type_info[] locals;
       
   263     }
       
   264 
       
   265     public static class full_frame extends stack_map_frame {
       
   266         full_frame(int frame_type, ClassReader cr)
       
   267                 throws IOException, InvalidStackMap {
       
   268             super(frame_type);
       
   269             offset_delta = cr.readUnsignedShort();
       
   270             number_of_locals = cr.readUnsignedShort();
       
   271             locals = new verification_type_info[number_of_locals];
       
   272             for (int i = 0; i < locals.length; i++)
       
   273                 locals[i] = verification_type_info.read(cr);
       
   274             number_of_stack_items = cr.readUnsignedShort();
       
   275             stack = new verification_type_info[number_of_stack_items];
       
   276             for (int i = 0; i < stack.length; i++)
       
   277                 stack[i] = verification_type_info.read(cr);
       
   278         }
       
   279 
       
   280         @Override
       
   281         public int length() {
       
   282             int n = super.length() + 2;
       
   283             for (verification_type_info local: locals)
       
   284                 n += local.length();
       
   285             n += 2;
       
   286             for (verification_type_info item: stack)
       
   287                 n += item.length();
       
   288             return n;
       
   289         }
       
   290 
       
   291         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   292             return visitor.visit_full_frame(this, data);
       
   293         }
       
   294 
       
   295         public int getOffsetDelta() {
       
   296             return offset_delta;
       
   297         }
       
   298 
       
   299         public final int offset_delta;
       
   300         public final int number_of_locals;
       
   301         public final verification_type_info[] locals;
       
   302         public final int number_of_stack_items;
       
   303         public final verification_type_info[] stack;
       
   304     }
       
   305 
       
   306     public static class verification_type_info {
       
   307         public static final int ITEM_Top = 0;
       
   308         public static final int ITEM_Integer = 1;
       
   309         public static final int ITEM_Float = 2;
       
   310         public static final int ITEM_Long = 4;
       
   311         public static final int ITEM_Double = 3;
       
   312         public static final int ITEM_Null = 5;
       
   313         public static final int ITEM_UninitializedThis = 6;
       
   314         public static final int ITEM_Object = 7;
       
   315         public static final int ITEM_Uninitialized = 8;
       
   316 
       
   317         static verification_type_info read(ClassReader cr)
       
   318                 throws IOException, InvalidStackMap {
       
   319             int tag = cr.readUnsignedByte();
       
   320             switch (tag) {
       
   321             case ITEM_Top:
       
   322             case ITEM_Integer:
       
   323             case ITEM_Float:
       
   324             case ITEM_Long:
       
   325             case ITEM_Double:
       
   326             case ITEM_Null:
       
   327             case ITEM_UninitializedThis:
       
   328                 return new verification_type_info(tag);
       
   329 
       
   330             case ITEM_Object:
       
   331                 return new Object_variable_info(cr);
       
   332 
       
   333             case ITEM_Uninitialized:
       
   334                 return new Uninitialized_variable_info(cr);
       
   335 
       
   336             default:
       
   337                 throw new InvalidStackMap("unrecognized verification_type_info tag");
       
   338             }
       
   339         }
       
   340 
       
   341         protected verification_type_info(int tag) {
       
   342             this.tag = tag;
       
   343         }
       
   344 
       
   345         public int length() {
       
   346             return 1;
       
   347         }
       
   348 
       
   349         public final int tag;
       
   350     }
       
   351 
       
   352     public static class Object_variable_info extends verification_type_info {
       
   353         Object_variable_info(ClassReader cr) throws IOException {
       
   354             super(ITEM_Object);
       
   355             cpool_index = cr.readUnsignedShort();
       
   356         }
       
   357 
       
   358         @Override
       
   359         public int length() {
       
   360             return super.length() + 2;
       
   361         }
       
   362 
       
   363         public final int cpool_index;
       
   364     }
       
   365 
       
   366     public static class Uninitialized_variable_info extends verification_type_info {
       
   367         Uninitialized_variable_info(ClassReader cr) throws IOException {
       
   368             super(ITEM_Uninitialized);
       
   369             offset = cr.readUnsignedShort();
       
   370         }
       
   371 
       
   372         @Override
       
   373         public int length() {
       
   374             return super.length() + 2;
       
   375         }
       
   376 
       
   377         public final int offset;
       
   378 
       
   379     }
       
   380 }