src/share/classes/com/sun/tools/javap/CodeWriter.java

Sat, 29 Sep 2012 09:00:58 -0700

author
ksrini
date
Sat, 29 Sep 2012 09:00:58 -0700
changeset 1346
20e4a54b1629
parent 815
d17f37522154
child 1521
71f35e4b93a5
permissions
-rw-r--r--

7198582: (java) Minor refactor of JavacParser
Reviewed-by: jjg, ksrini
Contributed-by: jan.lahoda@oracle.com

     1 /*
     2  * Copyright (c) 2007, 2012, 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  */
    26 package com.sun.tools.javap;
    28 import java.util.ArrayList;
    29 import java.util.List;
    31 import com.sun.tools.classfile.AccessFlags;
    32 import com.sun.tools.classfile.Code_attribute;
    33 import com.sun.tools.classfile.ConstantPool;
    34 import com.sun.tools.classfile.ConstantPoolException;
    35 import com.sun.tools.classfile.DescriptorException;
    36 import com.sun.tools.classfile.Instruction;
    37 import com.sun.tools.classfile.Instruction.TypeKind;
    38 import com.sun.tools.classfile.Method;
    40 /*
    41  *  Write the contents of a Code attribute.
    42  *
    43  *  <p><b>This is NOT part of any supported API.
    44  *  If you write code that depends on this, you do so at your own risk.
    45  *  This code and its internal interfaces are subject to change or
    46  *  deletion without notice.</b>
    47  */
    48 public class CodeWriter extends BasicWriter {
    49     public static CodeWriter instance(Context context) {
    50         CodeWriter instance = context.get(CodeWriter.class);
    51         if (instance == null)
    52             instance = new CodeWriter(context);
    53         return instance;
    54     }
    56     protected CodeWriter(Context context) {
    57         super(context);
    58         context.put(CodeWriter.class, this);
    59         attrWriter = AttributeWriter.instance(context);
    60         classWriter = ClassWriter.instance(context);
    61         constantWriter = ConstantWriter.instance(context);
    62         sourceWriter = SourceWriter.instance(context);
    63         tryBlockWriter = TryBlockWriter.instance(context);
    64         stackMapWriter = StackMapWriter.instance(context);
    65         localVariableTableWriter = LocalVariableTableWriter.instance(context);
    66         localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
    67         options = Options.instance(context);
    68     }
    70     void write(Code_attribute attr, ConstantPool constant_pool) {
    71         println("Code:");
    72         indent(+1);
    73         writeVerboseHeader(attr, constant_pool);
    74         writeInstrs(attr);
    75         writeExceptionTable(attr);
    76         attrWriter.write(attr, attr.attributes, constant_pool);
    77         indent(-1);
    78     }
    80     public void writeVerboseHeader(Code_attribute attr, ConstantPool constant_pool) {
    81         Method method = classWriter.getMethod();
    82         String argCount;
    83         try {
    84             int n = method.descriptor.getParameterCount(constant_pool);
    85             if (!method.access_flags.is(AccessFlags.ACC_STATIC))
    86                 ++n;  // for 'this'
    87             argCount = Integer.toString(n);
    88         } catch (ConstantPoolException e) {
    89             argCount = report(e);
    90         } catch (DescriptorException e) {
    91             argCount = report(e);
    92         }
    94         println("stack=" + attr.max_stack +
    95                 ", locals=" + attr.max_locals +
    96                 ", args_size=" + argCount);
    98     }
   100     public void writeInstrs(Code_attribute attr) {
   101         List<InstructionDetailWriter> detailWriters = getDetailWriters(attr);
   103         for (Instruction instr: attr.getInstructions()) {
   104             try {
   105                 for (InstructionDetailWriter w: detailWriters)
   106                     w.writeDetails(instr);
   107                 writeInstr(instr);
   108             } catch (ArrayIndexOutOfBoundsException e) {
   109                 println(report("error at or after byte " + instr.getPC()));
   110                 break;
   111             }
   112         }
   114         for (InstructionDetailWriter w: detailWriters)
   115             w.flush();
   116     }
   118     public void writeInstr(Instruction instr) {
   119         print(String.format("%4d: %-13s ", instr.getPC(), instr.getMnemonic()));
   120         // compute the number of indentations for the body of multi-line instructions
   121         // This is 6 (the width of "%4d: "), divided by the width of each indentation level,
   122         // and rounded up to the next integer.
   123         int indentWidth = options.indentWidth;
   124         int indent = (6 + indentWidth - 1) / indentWidth;
   125         instr.accept(instructionPrinter, indent);
   126         println();
   127     }
   128     // where
   129     Instruction.KindVisitor<Void,Integer> instructionPrinter =
   130             new Instruction.KindVisitor<Void,Integer>() {
   132         public Void visitNoOperands(Instruction instr, Integer indent) {
   133             return null;
   134         }
   136         public Void visitArrayType(Instruction instr, TypeKind kind, Integer indent) {
   137             print(" " + kind.name);
   138             return null;
   139         }
   141         public Void visitBranch(Instruction instr, int offset, Integer indent) {
   142             print((instr.getPC() + offset));
   143             return null;
   144         }
   146         public Void visitConstantPoolRef(Instruction instr, int index, Integer indent) {
   147             print("#" + index);
   148             tab();
   149             print("// ");
   150             printConstant(index);
   151             return null;
   152         }
   154         public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Integer indent) {
   155             print("#" + index + ",  " + value);
   156             tab();
   157             print("// ");
   158             printConstant(index);
   159             return null;
   160         }
   162         public Void visitLocal(Instruction instr, int index, Integer indent) {
   163             print(index);
   164             return null;
   165         }
   167         public Void visitLocalAndValue(Instruction instr, int index, int value, Integer indent) {
   168             print(index + ", " + value);
   169             return null;
   170         }
   172         public Void visitLookupSwitch(Instruction instr,
   173                 int default_, int npairs, int[] matches, int[] offsets, Integer indent) {
   174             int pc = instr.getPC();
   175             print("{ // " + npairs);
   176             indent(indent);
   177             for (int i = 0; i < npairs; i++) {
   178                 print(String.format("%n%12d: %d", matches[i], (pc + offsets[i])));
   179             }
   180             print("\n     default: " + (pc + default_) + "\n}");
   181             indent(-indent);
   182             return null;
   183         }
   185         public Void visitTableSwitch(Instruction instr,
   186                 int default_, int low, int high, int[] offsets, Integer indent) {
   187             int pc = instr.getPC();
   188             print("{ // " + low + " to " + high);
   189             indent(indent);
   190             for (int i = 0; i < offsets.length; i++) {
   191                 print(String.format("%n%12d: %d", (low + i), (pc + offsets[i])));
   192             }
   193             print("\n     default: " + (pc + default_) + "\n}");
   194             indent(-indent);
   195             return null;
   196         }
   198         public Void visitValue(Instruction instr, int value, Integer indent) {
   199             print(value);
   200             return null;
   201         }
   203         public Void visitUnknown(Instruction instr, Integer indent) {
   204             return null;
   205         }
   206     };
   209     public void writeExceptionTable(Code_attribute attr) {
   210         if (attr.exception_table_langth > 0) {
   211             println("Exception table:");
   212             indent(+1);
   213             println(" from    to  target type");
   214             for (int i = 0; i < attr.exception_table.length; i++) {
   215                 Code_attribute.Exception_data handler = attr.exception_table[i];
   216                 print(String.format(" %5d %5d %5d",
   217                         handler.start_pc, handler.end_pc, handler.handler_pc));
   218                 print("   ");
   219                 int catch_type = handler.catch_type;
   220                 if (catch_type == 0) {
   221                     println("any");
   222                 } else {
   223                     print("Class ");
   224                     println(constantWriter.stringValue(catch_type));
   225                 }
   226             }
   227             indent(-1);
   228         }
   230     }
   232     private void printConstant(int index) {
   233         constantWriter.write(index);
   234     }
   236     private List<InstructionDetailWriter> getDetailWriters(Code_attribute attr) {
   237         List<InstructionDetailWriter> detailWriters =
   238                 new ArrayList<InstructionDetailWriter>();
   239         if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
   240             sourceWriter.reset(classWriter.getClassFile(), attr);
   241             if (sourceWriter.hasSource())
   242                 detailWriters.add(sourceWriter);
   243             else
   244                 println("(Source code not available)");
   245         }
   247         if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {
   248             localVariableTableWriter.reset(attr);
   249             detailWriters.add(localVariableTableWriter);
   250         }
   252         if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VAR_TYPES)) {
   253             localVariableTypeTableWriter.reset(attr);
   254             detailWriters.add(localVariableTypeTableWriter);
   255         }
   257         if (options.details.contains(InstructionDetailWriter.Kind.STACKMAPS)) {
   258             stackMapWriter.reset(attr);
   259             stackMapWriter.writeInitialDetails();
   260             detailWriters.add(stackMapWriter);
   261         }
   263         if (options.details.contains(InstructionDetailWriter.Kind.TRY_BLOCKS)) {
   264             tryBlockWriter.reset(attr);
   265             detailWriters.add(tryBlockWriter);
   266         }
   268         return detailWriters;
   269     }
   271     private AttributeWriter attrWriter;
   272     private ClassWriter classWriter;
   273     private ConstantWriter constantWriter;
   274     private LocalVariableTableWriter localVariableTableWriter;
   275     private LocalVariableTypeTableWriter localVariableTypeTableWriter;
   276     private SourceWriter sourceWriter;
   277     private StackMapWriter stackMapWriter;
   278     private TryBlockWriter tryBlockWriter;
   279     private Options options;
   280 }

mercurial