Thu, 30 Jul 2009 09:18:55 -0700
4880672: javap does not output inner interfaces of an interface
Reviewed-by: mcimadamore
jjg@284 | 1 | /* |
jjg@284 | 2 | * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. |
jjg@284 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
jjg@284 | 4 | * |
jjg@284 | 5 | * This code is free software; you can redistribute it and/or modify it |
jjg@284 | 6 | * under the terms of the GNU General Public License version 2 only, as |
jjg@284 | 7 | * published by the Free Software Foundation. Sun designates this |
jjg@284 | 8 | * particular file as subject to the "Classpath" exception as provided |
jjg@284 | 9 | * by Sun in the LICENSE file that accompanied this code. |
jjg@284 | 10 | * |
jjg@284 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
jjg@284 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
jjg@284 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
jjg@284 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
jjg@284 | 15 | * accompanied this code). |
jjg@284 | 16 | * |
jjg@284 | 17 | * You should have received a copy of the GNU General Public License version |
jjg@284 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
jjg@284 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
jjg@284 | 20 | * |
jjg@284 | 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
jjg@284 | 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
jjg@284 | 23 | * have any questions. |
jjg@284 | 24 | */ |
jjg@284 | 25 | |
jjg@284 | 26 | package com.sun.tools.javap; |
jjg@284 | 27 | |
jjg@284 | 28 | import com.sun.tools.classfile.Attribute; |
jjg@284 | 29 | import com.sun.tools.classfile.Code_attribute; |
jjg@284 | 30 | import com.sun.tools.classfile.ConstantPool; |
jjg@284 | 31 | import com.sun.tools.classfile.ConstantPoolException; |
jjg@284 | 32 | import com.sun.tools.classfile.Descriptor; |
jjg@284 | 33 | import com.sun.tools.classfile.Descriptor.InvalidDescriptor; |
jjg@284 | 34 | import com.sun.tools.classfile.Instruction; |
jjg@284 | 35 | import com.sun.tools.classfile.LocalVariableTypeTable_attribute; |
jjg@284 | 36 | import com.sun.tools.classfile.Signature; |
jjg@284 | 37 | import java.util.ArrayList; |
jjg@284 | 38 | import java.util.HashMap; |
jjg@284 | 39 | import java.util.List; |
jjg@284 | 40 | import java.util.ListIterator; |
jjg@284 | 41 | import java.util.Map; |
jjg@284 | 42 | |
jjg@284 | 43 | /** |
jjg@284 | 44 | * Annotate instructions with details about local variables. |
jjg@284 | 45 | * |
jjg@284 | 46 | * <p><b>This is NOT part of any API supported by Sun Microsystems. If |
jjg@284 | 47 | * you write code that depends on this, you do so at your own risk. |
jjg@284 | 48 | * This code and its internal interfaces are subject to change or |
jjg@284 | 49 | * deletion without notice.</b> |
jjg@284 | 50 | */ |
jjg@284 | 51 | public class LocalVariableTypeTableWriter extends InstructionDetailWriter { |
jjg@284 | 52 | public enum NoteKind { |
jjg@284 | 53 | START("start") { |
jjg@284 | 54 | public boolean match(LocalVariableTypeTable_attribute.Entry entry, int pc) { |
jjg@284 | 55 | return (pc == entry.start_pc); |
jjg@284 | 56 | } |
jjg@284 | 57 | }, |
jjg@284 | 58 | END("end") { |
jjg@284 | 59 | public boolean match(LocalVariableTypeTable_attribute.Entry entry, int pc) { |
jjg@284 | 60 | return (pc == entry.start_pc + entry.length); |
jjg@284 | 61 | } |
jjg@284 | 62 | }; |
jjg@284 | 63 | NoteKind(String text) { |
jjg@284 | 64 | this.text = text; |
jjg@284 | 65 | } |
jjg@284 | 66 | public abstract boolean match(LocalVariableTypeTable_attribute.Entry entry, int pc); |
jjg@284 | 67 | public final String text; |
jjg@284 | 68 | }; |
jjg@284 | 69 | |
jjg@284 | 70 | static LocalVariableTypeTableWriter instance(Context context) { |
jjg@284 | 71 | LocalVariableTypeTableWriter instance = context.get(LocalVariableTypeTableWriter.class); |
jjg@284 | 72 | if (instance == null) |
jjg@284 | 73 | instance = new LocalVariableTypeTableWriter(context); |
jjg@284 | 74 | return instance; |
jjg@284 | 75 | } |
jjg@284 | 76 | |
jjg@284 | 77 | protected LocalVariableTypeTableWriter(Context context) { |
jjg@284 | 78 | super(context); |
jjg@284 | 79 | context.put(LocalVariableTypeTableWriter.class, this); |
jjg@284 | 80 | classWriter = ClassWriter.instance(context); |
jjg@284 | 81 | } |
jjg@284 | 82 | |
jjg@284 | 83 | public void reset(Code_attribute attr) { |
jjg@284 | 84 | codeAttr = attr; |
jjg@284 | 85 | pcMap = new HashMap<Integer, List<LocalVariableTypeTable_attribute.Entry>>(); |
jjg@284 | 86 | LocalVariableTypeTable_attribute lvt = |
jjg@284 | 87 | (LocalVariableTypeTable_attribute) (attr.attributes.get(Attribute.LocalVariableTypeTable)); |
jjg@284 | 88 | if (lvt == null) |
jjg@284 | 89 | return; |
jjg@284 | 90 | |
jjg@284 | 91 | for (int i = 0; i < lvt.local_variable_table.length; i++) { |
jjg@284 | 92 | LocalVariableTypeTable_attribute.Entry entry = lvt.local_variable_table[i]; |
jjg@284 | 93 | put(entry.start_pc, entry); |
jjg@284 | 94 | put(entry.start_pc + entry.length, entry); |
jjg@284 | 95 | } |
jjg@284 | 96 | } |
jjg@284 | 97 | |
jjg@284 | 98 | public void writeDetails(Instruction instr) { |
jjg@284 | 99 | int pc = instr.getPC(); |
jjg@284 | 100 | writeLocalVariables(pc, NoteKind.END); |
jjg@284 | 101 | writeLocalVariables(pc, NoteKind.START); |
jjg@284 | 102 | } |
jjg@284 | 103 | |
jjg@284 | 104 | @Override |
jjg@284 | 105 | public void flush() { |
jjg@284 | 106 | int pc = codeAttr.code_length; |
jjg@284 | 107 | writeLocalVariables(pc, NoteKind.END); |
jjg@284 | 108 | } |
jjg@284 | 109 | |
jjg@284 | 110 | public void writeLocalVariables(int pc, NoteKind kind) { |
jjg@284 | 111 | ConstantPool constant_pool = classWriter.getClassFile().constant_pool; |
jjg@284 | 112 | String indent = space(2); // get from Options? |
jjg@284 | 113 | List<LocalVariableTypeTable_attribute.Entry> entries = pcMap.get(pc); |
jjg@284 | 114 | if (entries != null) { |
jjg@284 | 115 | for (ListIterator<LocalVariableTypeTable_attribute.Entry> iter = |
jjg@284 | 116 | entries.listIterator(kind == NoteKind.END ? entries.size() : 0); |
jjg@284 | 117 | kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) { |
jjg@284 | 118 | LocalVariableTypeTable_attribute.Entry entry = |
jjg@284 | 119 | kind == NoteKind.END ? iter.previous() : iter.next(); |
jjg@284 | 120 | if (kind.match(entry, pc)) { |
jjg@284 | 121 | print(indent); |
jjg@284 | 122 | print(kind.text); |
jjg@284 | 123 | print(" generic local "); |
jjg@284 | 124 | print(entry.index); |
jjg@284 | 125 | print(" // "); |
jjg@284 | 126 | Descriptor d = new Signature(entry.signature_index); |
jjg@284 | 127 | try { |
jjg@284 | 128 | print(d.getFieldType(constant_pool)); |
jjg@284 | 129 | } catch (InvalidDescriptor e) { |
jjg@284 | 130 | print(report(e)); |
jjg@284 | 131 | } catch (ConstantPoolException e) { |
jjg@284 | 132 | print(report(e)); |
jjg@284 | 133 | } |
jjg@284 | 134 | print(" "); |
jjg@284 | 135 | try { |
jjg@284 | 136 | print(constant_pool.getUTF8Value(entry.name_index)); |
jjg@284 | 137 | } catch (ConstantPoolException e) { |
jjg@284 | 138 | print(report(e)); |
jjg@284 | 139 | } |
jjg@284 | 140 | println(); |
jjg@284 | 141 | } |
jjg@284 | 142 | } |
jjg@284 | 143 | } |
jjg@284 | 144 | } |
jjg@284 | 145 | |
jjg@284 | 146 | private void put(int pc, LocalVariableTypeTable_attribute.Entry entry) { |
jjg@284 | 147 | List<LocalVariableTypeTable_attribute.Entry> list = pcMap.get(pc); |
jjg@284 | 148 | if (list == null) { |
jjg@284 | 149 | list = new ArrayList<LocalVariableTypeTable_attribute.Entry>(); |
jjg@284 | 150 | pcMap.put(pc, list); |
jjg@284 | 151 | } |
jjg@284 | 152 | if (!list.contains(entry)) |
jjg@284 | 153 | list.add(entry); |
jjg@284 | 154 | } |
jjg@284 | 155 | |
jjg@284 | 156 | private ClassWriter classWriter; |
jjg@284 | 157 | private Code_attribute codeAttr; |
jjg@284 | 158 | private Map<Integer, List<LocalVariableTypeTable_attribute.Entry>> pcMap; |
jjg@284 | 159 | } |