LocalVariableTableWriter.java revision 2942:08092deced3f
1/* 2 * Copyright (c) 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 26package com.sun.tools.javap; 27 28import com.sun.tools.classfile.Attribute; 29import com.sun.tools.classfile.Code_attribute; 30import com.sun.tools.classfile.ConstantPool; 31import com.sun.tools.classfile.ConstantPoolException; 32import com.sun.tools.classfile.Descriptor; 33import com.sun.tools.classfile.Descriptor.InvalidDescriptor; 34import com.sun.tools.classfile.Instruction; 35import com.sun.tools.classfile.LocalVariableTable_attribute; 36import java.util.ArrayList; 37import java.util.HashMap; 38import java.util.List; 39import java.util.ListIterator; 40import java.util.Map; 41 42/** 43 * Annotate instructions with details about local variables. 44 * 45 * <p><b>This is NOT part of any supported API. 46 * If you write code that depends on this, you do so at your own risk. 47 * This code and its internal interfaces are subject to change or 48 * deletion without notice.</b> 49 */ 50public class LocalVariableTableWriter extends InstructionDetailWriter { 51 public enum NoteKind { 52 START("start") { 53 public boolean match(LocalVariableTable_attribute.Entry entry, int pc) { 54 return (pc == entry.start_pc); 55 } 56 }, 57 END("end") { 58 public boolean match(LocalVariableTable_attribute.Entry entry, int pc) { 59 return (pc == entry.start_pc + entry.length); 60 } 61 }; 62 NoteKind(String text) { 63 this.text = text; 64 } 65 public abstract boolean match(LocalVariableTable_attribute.Entry entry, int pc); 66 public final String text; 67 } 68 69 static LocalVariableTableWriter instance(Context context) { 70 LocalVariableTableWriter instance = context.get(LocalVariableTableWriter.class); 71 if (instance == null) 72 instance = new LocalVariableTableWriter(context); 73 return instance; 74 } 75 76 protected LocalVariableTableWriter(Context context) { 77 super(context); 78 context.put(LocalVariableTableWriter.class, this); 79 classWriter = ClassWriter.instance(context); 80 } 81 82 public void reset(Code_attribute attr) { 83 codeAttr = attr; 84 pcMap = new HashMap<>(); 85 LocalVariableTable_attribute lvt = 86 (LocalVariableTable_attribute) (attr.attributes.get(Attribute.LocalVariableTable)); 87 if (lvt == null) 88 return; 89 90 for (int i = 0; i < lvt.local_variable_table.length; i++) { 91 LocalVariableTable_attribute.Entry entry = lvt.local_variable_table[i]; 92 put(entry.start_pc, entry); 93 put(entry.start_pc + entry.length, entry); 94 } 95 } 96 97 public void writeDetails(Instruction instr) { 98 int pc = instr.getPC(); 99 writeLocalVariables(pc, NoteKind.END); 100 writeLocalVariables(pc, NoteKind.START); 101 } 102 103 @Override 104 public void flush() { 105 int pc = codeAttr.code_length; 106 writeLocalVariables(pc, NoteKind.END); 107 } 108 109 public void writeLocalVariables(int pc, NoteKind kind) { 110 ConstantPool constant_pool = classWriter.getClassFile().constant_pool; 111 String indent = space(2); // get from Options? 112 List<LocalVariableTable_attribute.Entry> entries = pcMap.get(pc); 113 if (entries != null) { 114 for (ListIterator<LocalVariableTable_attribute.Entry> iter = 115 entries.listIterator(kind == NoteKind.END ? entries.size() : 0); 116 kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) { 117 LocalVariableTable_attribute.Entry entry = 118 kind == NoteKind.END ? iter.previous() : iter.next(); 119 if (kind.match(entry, pc)) { 120 print(indent); 121 print(kind.text); 122 print(" local "); 123 print(entry.index); 124 print(" // "); 125 Descriptor d = new Descriptor(entry.descriptor_index); 126 try { 127 print(d.getFieldType(constant_pool)); 128 } catch (InvalidDescriptor e) { 129 print(report(e)); 130 } catch (ConstantPoolException e) { 131 print(report(e)); 132 } 133 print(" "); 134 try { 135 print(constant_pool.getUTF8Value(entry.name_index)); 136 } catch (ConstantPoolException e) { 137 print(report(e)); 138 } 139 println(); 140 } 141 } 142 } 143 } 144 145 private void put(int pc, LocalVariableTable_attribute.Entry entry) { 146 List<LocalVariableTable_attribute.Entry> list = pcMap.get(pc); 147 if (list == null) { 148 list = new ArrayList<>(); 149 pcMap.put(pc, list); 150 } 151 if (!list.contains(entry)) 152 list.add(entry); 153 } 154 155 private ClassWriter classWriter; 156 private Code_attribute codeAttr; 157 private Map<Integer, List<LocalVariableTable_attribute.Entry>> pcMap; 158} 159