6824493: experimental support for additional info for instructions

Tue, 19 May 2009 11:50:54 -0700

author
jjg
date
Tue, 19 May 2009 11:50:54 -0700
changeset 283
cd0630109de5
parent 282
fc634a593812
child 284
0c6cd88f72b9

6824493: experimental support for additional info for instructions
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/BasicWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/ClassWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/CodeWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/JavapTask.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/Messages.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/Options.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/SourceWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/StackMapWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/TryBlockWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/resources/javap.properties file | annotate | diff | comparison | revisions
test/tools/javap/T6824493.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java	Tue May 19 11:43:50 2009 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java	Tue May 19 11:50:54 2009 -0700
     1.3 @@ -107,6 +107,8 @@
     1.4              return 1;
     1.5          }
     1.6  
     1.7 +        public abstract int getOffsetDelta();
     1.8 +
     1.9          public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
    1.10  
    1.11          public final int frame_type;
    1.12 @@ -130,6 +132,10 @@
    1.13          public <R, D> R accept(Visitor<R, D> visitor, D data) {
    1.14              return visitor.visit_same_frame(this, data);
    1.15          }
    1.16 +
    1.17 +        public int getOffsetDelta() {
    1.18 +            return frame_type;
    1.19 +        }
    1.20      }
    1.21  
    1.22      public static class same_locals_1_stack_item_frame extends stack_map_frame {
    1.23 @@ -149,6 +155,10 @@
    1.24              return visitor.visit_same_locals_1_stack_item_frame(this, data);
    1.25          }
    1.26  
    1.27 +        public int getOffsetDelta() {
    1.28 +            return frame_type - 64;
    1.29 +        }
    1.30 +
    1.31          public final verification_type_info[] stack;
    1.32      }
    1.33  
    1.34 @@ -170,6 +180,10 @@
    1.35              return visitor.visit_same_locals_1_stack_item_frame_extended(this, data);
    1.36          }
    1.37  
    1.38 +        public int getOffsetDelta() {
    1.39 +            return offset_delta;
    1.40 +        }
    1.41 +
    1.42          public final int offset_delta;
    1.43          public final verification_type_info[] stack;
    1.44      }
    1.45 @@ -189,6 +203,10 @@
    1.46              return visitor.visit_chop_frame(this, data);
    1.47          }
    1.48  
    1.49 +        public int getOffsetDelta() {
    1.50 +            return offset_delta;
    1.51 +        }
    1.52 +
    1.53          public final int offset_delta;
    1.54      }
    1.55  
    1.56 @@ -207,6 +225,10 @@
    1.57              return visitor.visit_same_frame_extended(this, data);
    1.58          }
    1.59  
    1.60 +        public int getOffsetDelta() {
    1.61 +            return offset_delta;
    1.62 +        }
    1.63 +
    1.64          public final int offset_delta;
    1.65      }
    1.66  
    1.67 @@ -232,6 +254,10 @@
    1.68              return visitor.visit_append_frame(this, data);
    1.69          }
    1.70  
    1.71 +        public int getOffsetDelta() {
    1.72 +            return offset_delta;
    1.73 +        }
    1.74 +
    1.75          public final int offset_delta;
    1.76          public final verification_type_info[] locals;
    1.77      }
    1.78 @@ -266,6 +292,10 @@
    1.79              return visitor.visit_full_frame(this, data);
    1.80          }
    1.81  
    1.82 +        public int getOffsetDelta() {
    1.83 +            return offset_delta;
    1.84 +        }
    1.85 +
    1.86          public final int offset_delta;
    1.87          public final int number_of_locals;
    1.88          public final verification_type_info[] locals;
    1.89 @@ -308,7 +338,7 @@
    1.90              }
    1.91          }
    1.92  
    1.93 -        verification_type_info(int tag) {
    1.94 +        protected verification_type_info(int tag) {
    1.95              this.tag = tag;
    1.96          }
    1.97  
     2.1 --- a/src/share/classes/com/sun/tools/javap/BasicWriter.java	Tue May 19 11:43:50 2009 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javap/BasicWriter.java	Tue May 19 11:50:54 2009 -0700
     2.3 @@ -44,6 +44,9 @@
     2.4      protected BasicWriter(Context context) {
     2.5          lineWriter = LineWriter.instance(context);
     2.6          out = context.get(PrintWriter.class);
     2.7 +        messages = context.get(Messages.class);
     2.8 +        if (messages == null)
     2.9 +            throw new AssertionError();
    2.10      }
    2.11  
    2.12      protected void print(String s) {
    2.13 @@ -88,8 +91,26 @@
    2.14          return "???";
    2.15      }
    2.16  
    2.17 +    protected String space(int w) {
    2.18 +        if (w < spaces.length && spaces[w] != null)
    2.19 +            return spaces[w];
    2.20 +
    2.21 +        StringBuilder sb = new StringBuilder();
    2.22 +        for (int i = 0; i < w; i++)
    2.23 +            sb.append(" ");
    2.24 +
    2.25 +        String s = sb.toString();
    2.26 +        if (w < spaces.length)
    2.27 +            spaces[w] = s;
    2.28 +
    2.29 +        return s;
    2.30 +    }
    2.31 +
    2.32 +    private String[] spaces = new String[80];
    2.33 +
    2.34      private LineWriter lineWriter;
    2.35      private PrintWriter out;
    2.36 +    protected Messages messages;
    2.37  
    2.38      private static class LineWriter {
    2.39          static LineWriter instance(Context context) {
     3.1 --- a/src/share/classes/com/sun/tools/javap/ClassWriter.java	Tue May 19 11:43:50 2009 -0700
     3.2 +++ b/src/share/classes/com/sun/tools/javap/ClassWriter.java	Tue May 19 11:50:54 2009 -0700
     3.3 @@ -26,7 +26,9 @@
     3.4  package com.sun.tools.javap;
     3.5  
     3.6  import java.net.URI;
     3.7 +import java.text.DateFormat;
     3.8  import java.util.Collection;
     3.9 +import java.util.Date;
    3.10  import java.util.List;
    3.11  
    3.12  import com.sun.tools.classfile.AccessFlags;
    3.13 @@ -47,8 +49,6 @@
    3.14  import com.sun.tools.classfile.SourceFile_attribute;
    3.15  import com.sun.tools.classfile.Type;
    3.16  
    3.17 -import java.text.DateFormat;
    3.18 -import java.util.Date;
    3.19  import static com.sun.tools.classfile.AccessFlags.*;
    3.20  
    3.21  /*
     4.1 --- a/src/share/classes/com/sun/tools/javap/CodeWriter.java	Tue May 19 11:43:50 2009 -0700
     4.2 +++ b/src/share/classes/com/sun/tools/javap/CodeWriter.java	Tue May 19 11:50:54 2009 -0700
     4.3 @@ -25,6 +25,9 @@
     4.4  
     4.5  package com.sun.tools.javap;
     4.6  
     4.7 +import java.util.ArrayList;
     4.8 +import java.util.List;
     4.9 +
    4.10  import com.sun.tools.classfile.AccessFlags;
    4.11  import com.sun.tools.classfile.Code_attribute;
    4.12  import com.sun.tools.classfile.ConstantPool;
    4.13 @@ -33,9 +36,6 @@
    4.14  import com.sun.tools.classfile.Instruction;
    4.15  import com.sun.tools.classfile.Instruction.TypeKind;
    4.16  import com.sun.tools.classfile.Method;
    4.17 -import com.sun.tools.classfile.Opcode;
    4.18 -
    4.19 -//import static com.sun.tools.classfile.OpCodes.*;
    4.20  
    4.21  /*
    4.22   *  Write the contents of a Code attribute.
    4.23 @@ -59,6 +59,12 @@
    4.24          attrWriter = AttributeWriter.instance(context);
    4.25          classWriter = ClassWriter.instance(context);
    4.26          constantWriter = ConstantWriter.instance(context);
    4.27 +        sourceWriter = SourceWriter.instance(context);
    4.28 +        tryBlockWriter = TryBlockWriter.instance(context);
    4.29 +        stackMapWriter = StackMapWriter.instance(context);
    4.30 +        localVariableTableWriter = LocalVariableTableWriter.instance(context);
    4.31 +        localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
    4.32 +        options = Options.instance(context);
    4.33      }
    4.34  
    4.35      void write(Code_attribute attr, ConstantPool constant_pool) {
    4.36 @@ -90,14 +96,21 @@
    4.37      }
    4.38  
    4.39      public void writeInstrs(Code_attribute attr) {
    4.40 +        List<InstructionDetailWriter> detailWriters = getDetailWriters(attr);
    4.41 +
    4.42          for (Instruction instr: attr.getInstructions()) {
    4.43              try {
    4.44 +                for (InstructionDetailWriter w: detailWriters)
    4.45 +                    w.writeDetails(instr);
    4.46                  writeInstr(instr);
    4.47              } catch (ArrayIndexOutOfBoundsException e) {
    4.48                  println(report("error at or after byte " + instr.getPC()));
    4.49                  break;
    4.50              }
    4.51          }
    4.52 +
    4.53 +        for (InstructionDetailWriter w: detailWriters)
    4.54 +            w.flush();
    4.55      }
    4.56  
    4.57      public void writeInstr(Instruction instr) {
    4.58 @@ -211,11 +224,45 @@
    4.59          print(s);
    4.60      }
    4.61  
    4.62 -    private static int align(int n) {
    4.63 -        return (n + 3) & ~3;
    4.64 +    private List<InstructionDetailWriter> getDetailWriters(Code_attribute attr) {
    4.65 +        List<InstructionDetailWriter> detailWriters =
    4.66 +                new ArrayList<InstructionDetailWriter>();
    4.67 +        if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
    4.68 +            sourceWriter.reset(classWriter.getClassFile(), attr);
    4.69 +            detailWriters.add(sourceWriter);
    4.70 +        }
    4.71 +
    4.72 +        if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {
    4.73 +            localVariableTableWriter.reset(attr);
    4.74 +            detailWriters.add(localVariableTableWriter);
    4.75 +        }
    4.76 +
    4.77 +        if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VAR_TYPES)) {
    4.78 +            localVariableTypeTableWriter.reset(attr);
    4.79 +            detailWriters.add(localVariableTypeTableWriter);
    4.80 +        }
    4.81 +
    4.82 +        if (options.details.contains(InstructionDetailWriter.Kind.STACKMAPS)) {
    4.83 +            stackMapWriter.reset(attr);
    4.84 +            stackMapWriter.writeInitialDetails();
    4.85 +            detailWriters.add(stackMapWriter);
    4.86 +        }
    4.87 +
    4.88 +        if (options.details.contains(InstructionDetailWriter.Kind.TRY_BLOCKS)) {
    4.89 +            tryBlockWriter.reset(attr);
    4.90 +            detailWriters.add(tryBlockWriter);
    4.91 +        }
    4.92 +
    4.93 +        return detailWriters;
    4.94      }
    4.95  
    4.96      private AttributeWriter attrWriter;
    4.97      private ClassWriter classWriter;
    4.98      private ConstantWriter constantWriter;
    4.99 +    private LocalVariableTableWriter localVariableTableWriter;
   4.100 +    private LocalVariableTypeTableWriter localVariableTypeTableWriter;
   4.101 +    private SourceWriter sourceWriter;
   4.102 +    private StackMapWriter stackMapWriter;
   4.103 +    private TryBlockWriter tryBlockWriter;
   4.104 +    private Options options;
   4.105  }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java	Tue May 19 11:50:54 2009 -0700
     5.3 @@ -0,0 +1,57 @@
     5.4 +/*
     5.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Sun designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Sun in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    5.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    5.26 + * have any questions.
    5.27 + */
    5.28 +
    5.29 +package com.sun.tools.javap;
    5.30 +
    5.31 +import com.sun.tools.classfile.Instruction;
    5.32 +
    5.33 +
    5.34 +/*
    5.35 + *  Write additional details for an instruction.
    5.36 + *
    5.37 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    5.38 + *  you write code that depends on this, you do so at your own risk.
    5.39 + *  This code and its internal interfaces are subject to change or
    5.40 + *  deletion without notice.</b>
    5.41 + */
    5.42 +public abstract class InstructionDetailWriter extends BasicWriter {
    5.43 +    public enum Kind {
    5.44 +        LOCAL_VARS("localVariables"),
    5.45 +        LOCAL_VAR_TYPES("localVariableTypes"),
    5.46 +        SOURCE("source"),
    5.47 +        STACKMAPS("stackMaps"),
    5.48 +        TRY_BLOCKS("tryBlocks");
    5.49 +        Kind(String option) {
    5.50 +            this.option = option;
    5.51 +        }
    5.52 +        final String option;
    5.53 +    }
    5.54 +    InstructionDetailWriter(Context context) {
    5.55 +        super(context);
    5.56 +    }
    5.57 +
    5.58 +    abstract void writeDetails(Instruction instr);
    5.59 +    void flush() { }
    5.60 +}
     6.1 --- a/src/share/classes/com/sun/tools/javap/JavapTask.java	Tue May 19 11:43:50 2009 -0700
     6.2 +++ b/src/share/classes/com/sun/tools/javap/JavapTask.java	Tue May 19 11:50:54 2009 -0700
     6.3 @@ -39,6 +39,7 @@
     6.4  import java.text.MessageFormat;
     6.5  import java.util.ArrayList;
     6.6  import java.util.Arrays;
     6.7 +import java.util.EnumSet;
     6.8  import java.util.HashMap;
     6.9  import java.util.Iterator;
    6.10  import java.util.List;
    6.11 @@ -65,7 +66,7 @@
    6.12   *  This code and its internal interfaces are subject to change or
    6.13   *  deletion without notice.</b>
    6.14   */
    6.15 -public class JavapTask implements DisassemblerTool.DisassemblerTask {
    6.16 +public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
    6.17      public class BadArgs extends Exception {
    6.18          static final long serialVersionUID = 8765093759964640721L;
    6.19          BadArgs(String key, Object... args) {
    6.20 @@ -241,6 +242,56 @@
    6.21              }
    6.22          },
    6.23  
    6.24 +        new Option(false, "-XDdetails") {
    6.25 +            void process(JavapTask task, String opt, String arg) {
    6.26 +                task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
    6.27 +            }
    6.28 +
    6.29 +        },
    6.30 +
    6.31 +        new Option(false, "-XDdetails:") {
    6.32 +            @Override
    6.33 +            boolean matches(String opt) {
    6.34 +                int sep = opt.indexOf(":");
    6.35 +                return sep != -1 && super.matches(opt.substring(0, sep + 1));
    6.36 +            }
    6.37 +
    6.38 +            void process(JavapTask task, String opt, String arg) throws BadArgs {
    6.39 +                int sep = opt.indexOf(":");
    6.40 +                for (String v: opt.substring(sep + 1).split("[,: ]+")) {
    6.41 +                    if (!handleArg(task, v))
    6.42 +                        throw task.new BadArgs("err.invalid.arg.for.option", v);
    6.43 +                }
    6.44 +            }
    6.45 +
    6.46 +            boolean handleArg(JavapTask task, String arg) {
    6.47 +                if (arg.length() == 0)
    6.48 +                    return true;
    6.49 +
    6.50 +                if (arg.equals("all")) {
    6.51 +                    task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
    6.52 +                    return true;
    6.53 +                }
    6.54 +
    6.55 +                boolean on = true;
    6.56 +                if (arg.startsWith("-")) {
    6.57 +                    on = false;
    6.58 +                    arg = arg.substring(1);
    6.59 +                }
    6.60 +
    6.61 +                for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {
    6.62 +                    if (arg.equalsIgnoreCase(k.option)) {
    6.63 +                        if (on)
    6.64 +                            task.options.details.add(k);
    6.65 +                        else
    6.66 +                            task.options.details.remove(k);
    6.67 +                        return true;
    6.68 +                    }
    6.69 +                }
    6.70 +                return false;
    6.71 +            }
    6.72 +        },
    6.73 +
    6.74          new Option(false, "-constants") {
    6.75              void process(JavapTask task, String opt, String arg) {
    6.76                  task.options.showConstants = true;
    6.77 @@ -251,6 +302,7 @@
    6.78  
    6.79      JavapTask() {
    6.80          context = new Context();
    6.81 +        context.put(Messages.class, this);
    6.82          options = Options.instance(context);
    6.83      }
    6.84  
    6.85 @@ -469,6 +521,8 @@
    6.86  
    6.87          context.put(PrintWriter.class, log);
    6.88          ClassWriter classWriter = ClassWriter.instance(context);
    6.89 +        SourceWriter sourceWriter = SourceWriter.instance(context);
    6.90 +        sourceWriter.setFileManager(fileManager);
    6.91  
    6.92          boolean ok = true;
    6.93  
    6.94 @@ -651,11 +705,11 @@
    6.95  
    6.96      }
    6.97  
    6.98 -    private String getMessage(String key, Object... args) {
    6.99 +    public String getMessage(String key, Object... args) {
   6.100          return getMessage(task_locale, key, args);
   6.101      }
   6.102  
   6.103 -    private String getMessage(Locale locale, String key, Object... args) {
   6.104 +    public String getMessage(Locale locale, String key, Object... args) {
   6.105          if (bundles == null) {
   6.106              // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
   6.107              // and for efficiency, keep a hard reference to the bundle for the task
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/share/classes/com/sun/tools/javap/Messages.java	Tue May 19 11:50:54 2009 -0700
     7.3 @@ -0,0 +1,42 @@
     7.4 +/*
     7.5 + * Copyright 2007-2009 Sun Microsystems, Inc.  All Rights Reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.  Sun designates this
    7.11 + * particular file as subject to the "Classpath" exception as provided
    7.12 + * by Sun in the LICENSE file that accompanied this code.
    7.13 + *
    7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 + * version 2 for more details (a copy is included in the LICENSE file that
    7.18 + * accompanied this code).
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License version
    7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 + *
    7.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    7.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    7.26 + * have any questions.
    7.27 + */
    7.28 +
    7.29 +package com.sun.tools.javap;
    7.30 +
    7.31 +import java.util.Locale;
    7.32 +
    7.33 +/**
    7.34 + *  Access to javap messages.
    7.35 + *
    7.36 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    7.37 + *  you write code that depends on this, you do so at your own risk.
    7.38 + *  This code and its internal interfaces are subject to change or
    7.39 + *  deletion without notice.</b>
    7.40 + */
    7.41 +public interface Messages {
    7.42 +    String getMessage(String key, Object... args);
    7.43 +
    7.44 +    String getMessage(Locale locale, String key, Object... args);
    7.45 +}
     8.1 --- a/src/share/classes/com/sun/tools/javap/Options.java	Tue May 19 11:43:50 2009 -0700
     8.2 +++ b/src/share/classes/com/sun/tools/javap/Options.java	Tue May 19 11:50:54 2009 -0700
     8.3 @@ -25,8 +25,10 @@
     8.4  
     8.5  package com.sun.tools.javap;
     8.6  
     8.7 +import java.util.EnumSet;
     8.8  import java.util.HashSet;
     8.9  import java.util.Set;
    8.10 +
    8.11  import com.sun.tools.classfile.AccessFlags;
    8.12  
    8.13  /*
    8.14 @@ -77,6 +79,7 @@
    8.15      public boolean showLineAndLocalVariableTables;
    8.16      public int showAccess;
    8.17      public Set<String> accessOptions = new HashSet<String>();
    8.18 +    public Set<InstructionDetailWriter.Kind> details = EnumSet.noneOf(InstructionDetailWriter.Kind.class);
    8.19      public boolean showDisassembled;
    8.20      public boolean showInternalSignatures;
    8.21      public boolean showAllAttrs;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/share/classes/com/sun/tools/javap/SourceWriter.java	Tue May 19 11:50:54 2009 -0700
     9.3 @@ -0,0 +1,207 @@
     9.4 +/*
     9.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Sun designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Sun in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    9.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    9.26 + * have any questions.
    9.27 + */
    9.28 +
    9.29 +package com.sun.tools.javap;
    9.30 +
    9.31 +import java.io.BufferedReader;
    9.32 +import java.io.IOException;
    9.33 +import java.io.StringReader;
    9.34 +import java.util.ArrayList;
    9.35 +import java.util.List;
    9.36 +import java.util.Set;
    9.37 +import java.util.SortedMap;
    9.38 +import java.util.SortedSet;
    9.39 +import java.util.TreeMap;
    9.40 +import java.util.TreeSet;
    9.41 +import javax.tools.JavaFileManager;
    9.42 +import javax.tools.JavaFileManager.Location;
    9.43 +import javax.tools.JavaFileObject;
    9.44 +import javax.tools.StandardLocation;
    9.45 +
    9.46 +import com.sun.tools.classfile.Attribute;
    9.47 +import com.sun.tools.classfile.ClassFile;
    9.48 +import com.sun.tools.classfile.Code_attribute;
    9.49 +import com.sun.tools.classfile.ConstantPoolException;
    9.50 +import com.sun.tools.classfile.Instruction;
    9.51 +import com.sun.tools.classfile.LineNumberTable_attribute;
    9.52 +import com.sun.tools.classfile.SourceFile_attribute;
    9.53 +
    9.54 +
    9.55 +/**
    9.56 + * Annotate instructions with source code.
    9.57 + *
    9.58 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    9.59 + *  you write code that depends on this, you do so at your own risk.
    9.60 + *  This code and its internal interfaces are subject to change or
    9.61 + *  deletion without notice.</b>
    9.62 + */
    9.63 +public class SourceWriter extends InstructionDetailWriter {
    9.64 +    static SourceWriter instance(Context context) {
    9.65 +        SourceWriter instance = context.get(SourceWriter.class);
    9.66 +        if (instance == null)
    9.67 +            instance = new SourceWriter(context);
    9.68 +        return instance;
    9.69 +    }
    9.70 +
    9.71 +    protected SourceWriter(Context context) {
    9.72 +        super(context);
    9.73 +        context.put(SourceWriter.class, this);
    9.74 +    }
    9.75 +
    9.76 +    void setFileManager(JavaFileManager fileManager) {
    9.77 +        this.fileManager = fileManager;
    9.78 +    }
    9.79 +
    9.80 +    public void reset(ClassFile cf, Code_attribute attr) {
    9.81 +        setSource(cf);
    9.82 +        setLineMap(attr);
    9.83 +    }
    9.84 +
    9.85 +    public void writeDetails(Instruction instr) {
    9.86 +        String indent = space(40); // could get from Options?
    9.87 +        Set<Integer> lines = lineMap.get(instr.getPC());
    9.88 +        if (lines != null) {
    9.89 +            for (int line: lines) {
    9.90 +                print(indent);
    9.91 +                print(String.format(" %4d ", line));
    9.92 +                if (line < sourceLines.length)
    9.93 +                    print(sourceLines[line]);
    9.94 +                println();
    9.95 +                int nextLine = nextLine(line);
    9.96 +                for (int i = line + 1; i < nextLine; i++) {
    9.97 +                    print(indent);
    9.98 +                    print(String.format("(%4d)", i));
    9.99 +                    if (i < sourceLines.length)
   9.100 +                        print(sourceLines[i]);
   9.101 +                    println();
   9.102 +                }
   9.103 +            }
   9.104 +        }
   9.105 +
   9.106 +    }
   9.107 +
   9.108 +    private void setLineMap(Code_attribute attr) {
   9.109 +        SortedMap<Integer, SortedSet<Integer>> map =
   9.110 +                new TreeMap<Integer, SortedSet<Integer>>();
   9.111 +        SortedSet<Integer> allLines = new TreeSet<Integer>();
   9.112 +        for (Attribute a: attr.attributes) {
   9.113 +            if (a instanceof LineNumberTable_attribute) {
   9.114 +                LineNumberTable_attribute t = (LineNumberTable_attribute) a;
   9.115 +                for (LineNumberTable_attribute.Entry e: t.line_number_table) {
   9.116 +                    int start_pc = e.start_pc;
   9.117 +                    int line = e.line_number;
   9.118 +                    SortedSet<Integer> pcLines = map.get(start_pc);
   9.119 +                    if (pcLines == null) {
   9.120 +                        pcLines = new TreeSet<Integer>();
   9.121 +                        map.put(start_pc, pcLines);
   9.122 +                    }
   9.123 +                    pcLines.add(line);
   9.124 +                    allLines.add(line);
   9.125 +                }
   9.126 +            }
   9.127 +        }
   9.128 +        lineMap = map;
   9.129 +        lineList = new ArrayList<Integer>(allLines);
   9.130 +    }
   9.131 +
   9.132 +    private void setSource(ClassFile cf) {
   9.133 +        if (cf != classFile) {
   9.134 +            classFile = cf;
   9.135 +            sourceLines = splitLines(readSource(cf));
   9.136 +        }
   9.137 +    }
   9.138 +
   9.139 +    private String readSource(ClassFile cf) {
   9.140 +        Location location;
   9.141 +        if (fileManager.hasLocation((StandardLocation.SOURCE_PATH)))
   9.142 +            location = StandardLocation.SOURCE_PATH;
   9.143 +        else
   9.144 +            location = StandardLocation.CLASS_PATH;
   9.145 +
   9.146 +        // Guess the source file for a class from the package name for this
   9.147 +        // class and the base of the source file. This avoids having to read
   9.148 +        // additional classes to determine the outmost class from any
   9.149 +        // InnerClasses and EnclosingMethod attributes.
   9.150 +        try {
   9.151 +            String className = cf.getName();
   9.152 +            SourceFile_attribute sf =
   9.153 +                    (SourceFile_attribute) cf.attributes.get(Attribute.SourceFile);
   9.154 +            if (sf == null) {
   9.155 +                report(messages.getMessage("err.no.SourceFile.attribute"));
   9.156 +                return null;
   9.157 +            }
   9.158 +            String sourceFile = sf.getSourceFile(cf.constant_pool);
   9.159 +            String fileBase = sourceFile.endsWith(".java")
   9.160 +                ? sourceFile.substring(0, sourceFile.length() - 5) : sourceFile;
   9.161 +            int sep = className.lastIndexOf("/");
   9.162 +            String pkgName = (sep == -1 ? "" : className.substring(0, sep+1));
   9.163 +            String topClassName = (pkgName + fileBase).replace('/', '.');
   9.164 +            JavaFileObject fo =
   9.165 +                    fileManager.getJavaFileForInput(location,
   9.166 +                    topClassName,
   9.167 +                    JavaFileObject.Kind.SOURCE);
   9.168 +            if (fo == null) {
   9.169 +                report(messages.getMessage("err.source.file.not.found"));
   9.170 +                return null;
   9.171 +            }
   9.172 +            return fo.getCharContent(true).toString();
   9.173 +        } catch (ConstantPoolException e) {
   9.174 +            report(e);
   9.175 +            return null;
   9.176 +        } catch (IOException e) {
   9.177 +            report(e.getLocalizedMessage());
   9.178 +            return null;
   9.179 +        }
   9.180 +    }
   9.181 +
   9.182 +    private static String[] splitLines(String text) {
   9.183 +        if (text == null)
   9.184 +            return new String[0];
   9.185 +
   9.186 +        List<String> lines = new ArrayList<String>();
   9.187 +        lines.add(""); // dummy line 0
   9.188 +        try {
   9.189 +            BufferedReader r = new BufferedReader(new StringReader(text));
   9.190 +            String line;
   9.191 +            while ((line = r.readLine()) != null)
   9.192 +                lines.add(line);
   9.193 +        } catch (IOException ignore) {
   9.194 +        }
   9.195 +        return lines.toArray(new String[lines.size()]);
   9.196 +    }
   9.197 +
   9.198 +    private int nextLine(int line) {
   9.199 +        int i = lineList.indexOf(line);
   9.200 +        if (i == -1 || i == lineList.size() - 1)
   9.201 +            return - 1;
   9.202 +        return lineList.get(i + 1);
   9.203 +    }
   9.204 +
   9.205 +    private JavaFileManager fileManager;
   9.206 +    private ClassFile classFile;
   9.207 +    private SortedMap<Integer, SortedSet<Integer>> lineMap;
   9.208 +    private List<Integer> lineList;
   9.209 +    private String[] sourceLines;
   9.210 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/share/classes/com/sun/tools/javap/StackMapWriter.java	Tue May 19 11:50:54 2009 -0700
    10.3 @@ -0,0 +1,291 @@
    10.4 +/*
    10.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Sun designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Sun in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   10.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   10.26 + * have any questions.
   10.27 + */
   10.28 +
   10.29 +package com.sun.tools.javap;
   10.30 +
   10.31 +import com.sun.tools.classfile.AccessFlags;
   10.32 +import java.util.HashMap;
   10.33 +import java.util.Map;
   10.34 +
   10.35 +import com.sun.tools.classfile.Attribute;
   10.36 +import com.sun.tools.classfile.Code_attribute;
   10.37 +import com.sun.tools.classfile.ConstantPool;
   10.38 +import com.sun.tools.classfile.ConstantPoolException;
   10.39 +import com.sun.tools.classfile.Descriptor;
   10.40 +import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
   10.41 +import com.sun.tools.classfile.Instruction;
   10.42 +import com.sun.tools.classfile.Method;
   10.43 +import com.sun.tools.classfile.StackMapTable_attribute;
   10.44 +import com.sun.tools.classfile.StackMapTable_attribute.*;
   10.45 +
   10.46 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
   10.47 +
   10.48 +/**
   10.49 + * Annotate instructions with stack map.
   10.50 + *
   10.51 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   10.52 + *  you write code that depends on this, you do so at your own risk.
   10.53 + *  This code and its internal interfaces are subject to change or
   10.54 + *  deletion without notice.</b>
   10.55 + */
   10.56 +public class StackMapWriter extends InstructionDetailWriter {
   10.57 +    static StackMapWriter instance(Context context) {
   10.58 +        StackMapWriter instance = context.get(StackMapWriter.class);
   10.59 +        if (instance == null)
   10.60 +            instance = new StackMapWriter(context);
   10.61 +        return instance;
   10.62 +    }
   10.63 +
   10.64 +    protected StackMapWriter(Context context) {
   10.65 +        super(context);
   10.66 +        context.put(StackMapWriter.class, this);
   10.67 +        classWriter = ClassWriter.instance(context);
   10.68 +    }
   10.69 +
   10.70 +    public void reset(Code_attribute attr) {
   10.71 +        setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));
   10.72 +    }
   10.73 +
   10.74 +    void setStackMap(StackMapTable_attribute attr) {
   10.75 +        if (attr == null) {
   10.76 +            map = null;
   10.77 +            return;
   10.78 +        }
   10.79 +
   10.80 +        Method m = classWriter.getMethod();
   10.81 +        Descriptor d = m.descriptor;
   10.82 +        String[] args;
   10.83 +        try {
   10.84 +            ConstantPool cp = classWriter.getClassFile().constant_pool;
   10.85 +            String argString = d.getParameterTypes(cp);
   10.86 +            args = argString.substring(1, argString.length() - 1).split("[, ]+");
   10.87 +        } catch (ConstantPoolException e) {
   10.88 +            return;
   10.89 +        } catch (InvalidDescriptor e) {
   10.90 +            return;
   10.91 +        }
   10.92 +        boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
   10.93 +
   10.94 +        verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];
   10.95 +        if (!isStatic)
   10.96 +            initialLocals[0] = new CustomVerificationTypeInfo("this");
   10.97 +        for (int i = 0; i < args.length; i++) {
   10.98 +            initialLocals[(isStatic ? 0 : 1) + i] =
   10.99 +                    new CustomVerificationTypeInfo(args[i].replace(".", "/"));
  10.100 +        }
  10.101 +
  10.102 +        map = new HashMap<Integer, StackMap>();
  10.103 +        StackMapBuilder builder = new StackMapBuilder();
  10.104 +
  10.105 +        // using -1 as the pc for the initial frame effectively compensates for
  10.106 +        // the difference in behavior for the first stack map frame (where the
  10.107 +        // pc offset is just offset_delta) compared to subsequent frames (where
  10.108 +        // the pc offset is always offset_delta+1).
  10.109 +        int pc = -1;
  10.110 +
  10.111 +        map.put(pc, new StackMap(initialLocals, empty));
  10.112 +
  10.113 +        for (int i = 0; i < attr.entries.length; i++)
  10.114 +            pc = attr.entries[i].accept(builder, pc);
  10.115 +    }
  10.116 +
  10.117 +    public void writeInitialDetails() {
  10.118 +        writeDetails(-1);
  10.119 +    }
  10.120 +
  10.121 +    public void writeDetails(Instruction instr) {
  10.122 +        writeDetails(instr.getPC());
  10.123 +    }
  10.124 +
  10.125 +    private void writeDetails(int pc) {
  10.126 +        if (map == null)
  10.127 +            return;
  10.128 +
  10.129 +        StackMap m = map.get(pc);
  10.130 +        if (m != null) {
  10.131 +            print("StackMap locals: ", m.locals);
  10.132 +            print("StackMap stack: ", m.stack);
  10.133 +        }
  10.134 +
  10.135 +    }
  10.136 +
  10.137 +    void print(String label, verification_type_info[] entries) {
  10.138 +        print(label);
  10.139 +        for (int i = 0; i < entries.length; i++) {
  10.140 +            print(" ");
  10.141 +            print(entries[i]);
  10.142 +        }
  10.143 +        println();
  10.144 +    }
  10.145 +
  10.146 +    void print(verification_type_info entry) {
  10.147 +        if (entry == null) {
  10.148 +            print("ERROR");
  10.149 +            return;
  10.150 +        }
  10.151 +
  10.152 +        switch (entry.tag) {
  10.153 +            case -1:
  10.154 +                print(((CustomVerificationTypeInfo) entry).text);
  10.155 +                break;
  10.156 +
  10.157 +            case ITEM_Top:
  10.158 +                print("top");
  10.159 +                break;
  10.160 +
  10.161 +            case ITEM_Integer:
  10.162 +                print("int");
  10.163 +                break;
  10.164 +
  10.165 +            case ITEM_Float:
  10.166 +                print("float");
  10.167 +                break;
  10.168 +
  10.169 +            case ITEM_Long:
  10.170 +                print("long");
  10.171 +                break;
  10.172 +
  10.173 +            case ITEM_Double:
  10.174 +                print("double");
  10.175 +                break;
  10.176 +
  10.177 +            case ITEM_Null:
  10.178 +                print("null");
  10.179 +                break;
  10.180 +
  10.181 +            case ITEM_UninitializedThis:
  10.182 +                print("uninit_this");
  10.183 +                break;
  10.184 +
  10.185 +            case ITEM_Object:
  10.186 +                try {
  10.187 +                    ConstantPool cp = classWriter.getClassFile().constant_pool;
  10.188 +                    ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);
  10.189 +                    print(cp.getUTF8Value(class_info.name_index));
  10.190 +                } catch (ConstantPoolException e) {
  10.191 +                    print("??");
  10.192 +                }
  10.193 +                break;
  10.194 +
  10.195 +            case ITEM_Uninitialized:
  10.196 +                print(((Uninitialized_variable_info) entry).offset);
  10.197 +                break;
  10.198 +        }
  10.199 +
  10.200 +    }
  10.201 +
  10.202 +    private Map<Integer, StackMap> map;
  10.203 +    private ClassWriter classWriter;
  10.204 +
  10.205 +    class StackMapBuilder
  10.206 +            implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {
  10.207 +
  10.208 +        public Integer visit_same_frame(same_frame frame, Integer pc) {
  10.209 +            int new_pc = pc + frame.getOffsetDelta() + 1;
  10.210 +            StackMap m = map.get(pc);
  10.211 +            assert (m != null);
  10.212 +            map.put(new_pc, m);
  10.213 +            return new_pc;
  10.214 +        }
  10.215 +
  10.216 +        public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {
  10.217 +            int new_pc = pc + frame.getOffsetDelta() + 1;
  10.218 +            StackMap prev = map.get(pc);
  10.219 +            assert (prev != null);
  10.220 +            StackMap m = new StackMap(prev.locals, frame.stack);
  10.221 +            map.put(new_pc, m);
  10.222 +            return new_pc;
  10.223 +        }
  10.224 +
  10.225 +        public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {
  10.226 +            int new_pc = pc + frame.getOffsetDelta() + 1;
  10.227 +            StackMap prev = map.get(pc);
  10.228 +            assert (prev != null);
  10.229 +            StackMap m = new StackMap(prev.locals, frame.stack);
  10.230 +            map.put(new_pc, m);
  10.231 +            return new_pc;
  10.232 +        }
  10.233 +
  10.234 +        public Integer visit_chop_frame(chop_frame frame, Integer pc) {
  10.235 +            int new_pc = pc + frame.getOffsetDelta() + 1;
  10.236 +            StackMap prev = map.get(pc);
  10.237 +            assert (prev != null);
  10.238 +            int k = 251 - frame.frame_type;
  10.239 +            verification_type_info[] new_locals = new verification_type_info[prev.locals.length - k];
  10.240 +            System.arraycopy(prev.locals, 0, new_locals, 0, new_locals.length);
  10.241 +            StackMap m = new StackMap(new_locals, empty);
  10.242 +            map.put(new_pc, m);
  10.243 +            return new_pc;
  10.244 +        }
  10.245 +
  10.246 +        public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {
  10.247 +            int new_pc = pc + frame.getOffsetDelta();
  10.248 +            StackMap m = map.get(pc);
  10.249 +            assert (m != null);
  10.250 +            map.put(new_pc, m);
  10.251 +            return new_pc;
  10.252 +        }
  10.253 +
  10.254 +        public Integer visit_append_frame(append_frame frame, Integer pc) {
  10.255 +            int new_pc = pc + frame.getOffsetDelta() + 1;
  10.256 +            StackMap prev = map.get(pc);
  10.257 +            assert (prev != null);
  10.258 +            verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];
  10.259 +            System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);
  10.260 +            System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);
  10.261 +            StackMap m = new StackMap(new_locals, empty);
  10.262 +            map.put(new_pc, m);
  10.263 +            return new_pc;
  10.264 +        }
  10.265 +
  10.266 +        public Integer visit_full_frame(full_frame frame, Integer pc) {
  10.267 +            int new_pc = pc + frame.getOffsetDelta() + 1;
  10.268 +            StackMap m = new StackMap(frame.locals, frame.stack);
  10.269 +            map.put(new_pc, m);
  10.270 +            return new_pc;
  10.271 +        }
  10.272 +
  10.273 +    }
  10.274 +
  10.275 +    class StackMap {
  10.276 +        StackMap(verification_type_info[] locals, verification_type_info[] stack) {
  10.277 +            this.locals = locals;
  10.278 +            this.stack = stack;
  10.279 +        }
  10.280 +
  10.281 +        private final verification_type_info[] locals;
  10.282 +        private final verification_type_info[] stack;
  10.283 +    }
  10.284 +
  10.285 +    class CustomVerificationTypeInfo extends verification_type_info {
  10.286 +        public CustomVerificationTypeInfo(String text) {
  10.287 +            super(-1);
  10.288 +            this.text = text;
  10.289 +        }
  10.290 +        private String text;
  10.291 +    }
  10.292 +
  10.293 +    private final verification_type_info[] empty = { };
  10.294 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/share/classes/com/sun/tools/javap/TryBlockWriter.java	Tue May 19 11:50:54 2009 -0700
    11.3 @@ -0,0 +1,142 @@
    11.4 +/*
    11.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Sun designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Sun in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   11.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   11.26 + * have any questions.
   11.27 + */
   11.28 +
   11.29 +package com.sun.tools.javap;
   11.30 +
   11.31 +import com.sun.tools.classfile.Code_attribute;
   11.32 +import com.sun.tools.classfile.Code_attribute.Exception_data;
   11.33 +import com.sun.tools.classfile.Instruction;
   11.34 +import java.util.ArrayList;
   11.35 +import java.util.HashMap;
   11.36 +import java.util.List;
   11.37 +import java.util.ListIterator;
   11.38 +import java.util.Map;
   11.39 +
   11.40 +/**
   11.41 + * Annotate instructions with details about try blocks.
   11.42 + *
   11.43 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   11.44 + *  you write code that depends on this, you do so at your own risk.
   11.45 + *  This code and its internal interfaces are subject to change or
   11.46 + *  deletion without notice.</b>
   11.47 + */
   11.48 +public class TryBlockWriter extends InstructionDetailWriter {
   11.49 +    public enum NoteKind {
   11.50 +        START("try") {
   11.51 +            public boolean match(Exception_data entry, int pc) {
   11.52 +                return (pc == entry.start_pc);
   11.53 +            }
   11.54 +        },
   11.55 +        END("end try") {
   11.56 +            public boolean match(Exception_data entry, int pc) {
   11.57 +                return (pc == entry.end_pc);
   11.58 +            }
   11.59 +        },
   11.60 +        HANDLER("catch") {
   11.61 +            public boolean match(Exception_data entry, int pc) {
   11.62 +                return (pc == entry.handler_pc);
   11.63 +            }
   11.64 +        };
   11.65 +        NoteKind(String text) {
   11.66 +            this.text = text;
   11.67 +        }
   11.68 +        public abstract boolean match(Exception_data entry, int pc);
   11.69 +        public final String text;
   11.70 +    };
   11.71 +
   11.72 +    static TryBlockWriter instance(Context context) {
   11.73 +        TryBlockWriter instance = context.get(TryBlockWriter.class);
   11.74 +        if (instance == null)
   11.75 +            instance = new TryBlockWriter(context);
   11.76 +        return instance;
   11.77 +    }
   11.78 +
   11.79 +    protected TryBlockWriter(Context context) {
   11.80 +        super(context);
   11.81 +        context.put(TryBlockWriter.class, this);
   11.82 +        constantWriter = ConstantWriter.instance(context);
   11.83 +    }
   11.84 +
   11.85 +    public void reset(Code_attribute attr) {
   11.86 +        indexMap = new HashMap<Exception_data, Integer>();
   11.87 +        pcMap = new HashMap<Integer, List<Exception_data>>();
   11.88 +        for (int i = 0; i < attr.exception_table.length; i++) {
   11.89 +            Exception_data entry = attr.exception_table[i];
   11.90 +            indexMap.put(entry, i);
   11.91 +            put(entry.start_pc, entry);
   11.92 +            put(entry.end_pc, entry);
   11.93 +            put(entry.handler_pc, entry);
   11.94 +        }
   11.95 +    }
   11.96 +
   11.97 +    public void writeDetails(Instruction instr) {
   11.98 +        writeTrys(instr, NoteKind.END);
   11.99 +        writeTrys(instr, NoteKind.START);
  11.100 +        writeTrys(instr, NoteKind.HANDLER);
  11.101 +    }
  11.102 +
  11.103 +    public void writeTrys(Instruction instr, NoteKind kind) {
  11.104 +        String indent = space(2); // get from Options?
  11.105 +        int pc = instr.getPC();
  11.106 +        List<Exception_data> entries = pcMap.get(pc);
  11.107 +        if (entries != null) {
  11.108 +            for (ListIterator<Exception_data> iter =
  11.109 +                    entries.listIterator(kind == NoteKind.END ? entries.size() : 0);
  11.110 +                    kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) {
  11.111 +                Exception_data entry =
  11.112 +                        kind == NoteKind.END ? iter.previous() : iter.next();
  11.113 +                if (kind.match(entry, pc)) {
  11.114 +                    print(indent);
  11.115 +                    print(kind.text);
  11.116 +                    print("[");
  11.117 +                    print(indexMap.get(entry));
  11.118 +                    print("] ");
  11.119 +                    if (entry.catch_type == 0)
  11.120 +                        print("finally");
  11.121 +                    else {
  11.122 +                        print("#" + entry.catch_type);
  11.123 +                        print(" // ");
  11.124 +                        constantWriter.write(entry.catch_type);
  11.125 +                    }
  11.126 +                    println();
  11.127 +                }
  11.128 +            }
  11.129 +        }
  11.130 +    }
  11.131 +
  11.132 +    private void put(int pc, Exception_data entry) {
  11.133 +        List<Exception_data> list = pcMap.get(pc);
  11.134 +        if (list == null) {
  11.135 +            list = new ArrayList<Exception_data>();
  11.136 +            pcMap.put(pc, list);
  11.137 +        }
  11.138 +        if (!list.contains(entry))
  11.139 +            list.add(entry);
  11.140 +    }
  11.141 +
  11.142 +    private Map<Integer, List<Exception_data>> pcMap;
  11.143 +    private Map<Exception_data, Integer> indexMap;
  11.144 +    private ConstantWriter constantWriter;
  11.145 +}
    12.1 --- a/src/share/classes/com/sun/tools/javap/resources/javap.properties	Tue May 19 11:43:50 2009 -0700
    12.2 +++ b/src/share/classes/com/sun/tools/javap/resources/javap.properties	Tue May 19 11:50:54 2009 -0700
    12.3 @@ -9,6 +9,7 @@
    12.4  err.h.not.supported=-h is no longer available - use the 'javah' program
    12.5  err.incompatible.options=bad combination of options: {0}
    12.6  err.internal.error=internal error: {0} {1} {2}
    12.7 +err.invalid.arg.for.option=invalid argument for option: {0}
    12.8  err.ioerror=IO error reading {0}: {1}
    12.9  err.missing.arg=no value given for {0}
   12.10  err.no.classes.specified=no classes specified
   12.11 @@ -16,6 +17,8 @@
   12.12  err.unknown.option=unknown option: {0}
   12.13  err.verify.not.supported=-verify not supported
   12.14  err.Xold.not.supported.here=-Xold must be given as the first option
   12.15 +err.no.SourceFile.attribute=no SourceFile attribute
   12.16 +err.source.file.not.found=source file not found
   12.17  
   12.18  main.usage.summary=\
   12.19  Usage: {0} <options> <classes>\n\
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/tools/javap/T6824493.java	Tue May 19 11:50:54 2009 -0700
    13.3 @@ -0,0 +1,116 @@
    13.4 +/*
    13.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + *
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + *
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + *
   13.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   13.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   13.24 + * have any questions.
   13.25 + */
   13.26 +
   13.27 +import java.io.*;
   13.28 +import java.util.*;
   13.29 +
   13.30 +/*
   13.31 + * @test
   13.32 + * @bug 6824493
   13.33 + * @summary experimental support for additional info for instructions
   13.34 + * @compile -g T6824493.java
   13.35 + * @run main T6824493
   13.36 + */
   13.37 +public class T6824493 {
   13.38 +    public static void main(String... args) {
   13.39 +        new T6824493().run();
   13.40 +    }
   13.41 +
   13.42 +    void run() {
   13.43 +        // for each of the options, we run javap and check for some
   13.44 +        // marker strings in the output that generally indicate the
   13.45 +        // presence of the expected output, without being as specific
   13.46 +        // as a full golden file test.
   13.47 +        test("-XDdetails:source",
   13.48 +            "for (int i = 0; i < 10; i++) {",
   13.49 +            "System.out.println(s + i);");
   13.50 +
   13.51 +        test("-XDdetails:tryBlocks",
   13.52 +                "try[0]",
   13.53 +                "end try[0]",
   13.54 +                "catch[0]");
   13.55 +
   13.56 +        test("-XDdetails:stackMaps",
   13.57 +                "StackMap locals:  this java/lang/String int",
   13.58 +                "StackMap stack:  java/lang/Throwable");
   13.59 +
   13.60 +        test("-XDdetails:localVariables",
   13.61 +                "start local 3 // java.util.List list",
   13.62 +                "end local 3 // java.util.List list");
   13.63 +
   13.64 +        test("-XDdetails:localVariableTypes",
   13.65 +                "start generic local 3 // java.util.List<java.lang.String> list",
   13.66 +                "end generic local 3 // java.util.List<java.lang.String> list");
   13.67 +
   13.68 +        if (errors > 0)
   13.69 +            throw new Error(errors + " errors found");
   13.70 +    }
   13.71 +
   13.72 +    void test(String option, String... expect) {
   13.73 +        String[] args = {
   13.74 +            "-c",
   13.75 +            "-classpath",
   13.76 +            testSrc + File.pathSeparator + testClasses,
   13.77 +            option,
   13.78 +            "Test"
   13.79 +        };
   13.80 +        StringWriter sw = new StringWriter();
   13.81 +        PrintWriter pw = new PrintWriter(sw);
   13.82 +        int rc = com.sun.tools.javap.Main.run(args, pw);
   13.83 +        if (rc != 0) {
   13.84 +            error("unexpected return code from javap: " + rc);
   13.85 +            return;
   13.86 +        }
   13.87 +
   13.88 +        String out = sw.toString();
   13.89 +        System.out.println(out);
   13.90 +        for (String e: expect) {
   13.91 +            if (!out.contains(e))
   13.92 +                error("Not found: " + e);
   13.93 +        }
   13.94 +    }
   13.95 +
   13.96 +    void error(String msg) {
   13.97 +        System.err.println("Error: " + msg);
   13.98 +        errors++;
   13.99 +    }
  13.100 +
  13.101 +    private int errors;
  13.102 +    private String testSrc = System.getProperty("test.src", ".");
  13.103 +    private String testClasses = System.getProperty("test.classes", ".");
  13.104 +}
  13.105 +
  13.106 +class Test {
  13.107 +    void m(String s) {
  13.108 +        for (int i = 0; i < 10; i++) {
  13.109 +            try {
  13.110 +                List<String> list = null;
  13.111 +                System.out.println(s + i);
  13.112 +            } catch (NullPointerException e) {
  13.113 +                System.out.println("catch NPE");
  13.114 +            } finally {
  13.115 +                System.out.println("finally");
  13.116 +            }
  13.117 +        }
  13.118 +    }
  13.119 +}

mercurial