jjg@283: /* jjg@283: * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. jjg@283: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@283: * jjg@283: * This code is free software; you can redistribute it and/or modify it jjg@283: * under the terms of the GNU General Public License version 2 only, as jjg@283: * published by the Free Software Foundation. Sun designates this jjg@283: * particular file as subject to the "Classpath" exception as provided jjg@283: * by Sun in the LICENSE file that accompanied this code. jjg@283: * jjg@283: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@283: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@283: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@283: * version 2 for more details (a copy is included in the LICENSE file that jjg@283: * accompanied this code). jjg@283: * jjg@283: * You should have received a copy of the GNU General Public License version jjg@283: * 2 along with this work; if not, write to the Free Software Foundation, jjg@283: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@283: * jjg@283: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, jjg@283: * CA 95054 USA or visit www.sun.com if you need additional information or jjg@283: * have any questions. jjg@283: */ jjg@283: jjg@283: package com.sun.tools.javap; jjg@283: jjg@283: import com.sun.tools.classfile.Code_attribute; jjg@283: import com.sun.tools.classfile.Code_attribute.Exception_data; jjg@283: import com.sun.tools.classfile.Instruction; jjg@283: import java.util.ArrayList; jjg@283: import java.util.HashMap; jjg@283: import java.util.List; jjg@283: import java.util.ListIterator; jjg@283: import java.util.Map; jjg@283: jjg@283: /** jjg@283: * Annotate instructions with details about try blocks. jjg@283: * jjg@283: *

This is NOT part of any API supported by Sun Microsystems. If jjg@283: * you write code that depends on this, you do so at your own risk. jjg@283: * This code and its internal interfaces are subject to change or jjg@283: * deletion without notice. jjg@283: */ jjg@283: public class TryBlockWriter extends InstructionDetailWriter { jjg@283: public enum NoteKind { jjg@283: START("try") { jjg@283: public boolean match(Exception_data entry, int pc) { jjg@283: return (pc == entry.start_pc); jjg@283: } jjg@283: }, jjg@283: END("end try") { jjg@283: public boolean match(Exception_data entry, int pc) { jjg@283: return (pc == entry.end_pc); jjg@283: } jjg@283: }, jjg@283: HANDLER("catch") { jjg@283: public boolean match(Exception_data entry, int pc) { jjg@283: return (pc == entry.handler_pc); jjg@283: } jjg@283: }; jjg@283: NoteKind(String text) { jjg@283: this.text = text; jjg@283: } jjg@283: public abstract boolean match(Exception_data entry, int pc); jjg@283: public final String text; jjg@283: }; jjg@283: jjg@283: static TryBlockWriter instance(Context context) { jjg@283: TryBlockWriter instance = context.get(TryBlockWriter.class); jjg@283: if (instance == null) jjg@283: instance = new TryBlockWriter(context); jjg@283: return instance; jjg@283: } jjg@283: jjg@283: protected TryBlockWriter(Context context) { jjg@283: super(context); jjg@283: context.put(TryBlockWriter.class, this); jjg@283: constantWriter = ConstantWriter.instance(context); jjg@283: } jjg@283: jjg@283: public void reset(Code_attribute attr) { jjg@283: indexMap = new HashMap(); jjg@283: pcMap = new HashMap>(); jjg@283: for (int i = 0; i < attr.exception_table.length; i++) { jjg@283: Exception_data entry = attr.exception_table[i]; jjg@283: indexMap.put(entry, i); jjg@283: put(entry.start_pc, entry); jjg@283: put(entry.end_pc, entry); jjg@283: put(entry.handler_pc, entry); jjg@283: } jjg@283: } jjg@283: jjg@283: public void writeDetails(Instruction instr) { jjg@283: writeTrys(instr, NoteKind.END); jjg@283: writeTrys(instr, NoteKind.START); jjg@283: writeTrys(instr, NoteKind.HANDLER); jjg@283: } jjg@283: jjg@283: public void writeTrys(Instruction instr, NoteKind kind) { jjg@283: String indent = space(2); // get from Options? jjg@283: int pc = instr.getPC(); jjg@283: List entries = pcMap.get(pc); jjg@283: if (entries != null) { jjg@283: for (ListIterator iter = jjg@283: entries.listIterator(kind == NoteKind.END ? entries.size() : 0); jjg@283: kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) { jjg@283: Exception_data entry = jjg@283: kind == NoteKind.END ? iter.previous() : iter.next(); jjg@283: if (kind.match(entry, pc)) { jjg@283: print(indent); jjg@283: print(kind.text); jjg@283: print("["); jjg@283: print(indexMap.get(entry)); jjg@283: print("] "); jjg@283: if (entry.catch_type == 0) jjg@283: print("finally"); jjg@283: else { jjg@283: print("#" + entry.catch_type); jjg@283: print(" // "); jjg@283: constantWriter.write(entry.catch_type); jjg@283: } jjg@283: println(); jjg@283: } jjg@283: } jjg@283: } jjg@283: } jjg@283: jjg@283: private void put(int pc, Exception_data entry) { jjg@283: List list = pcMap.get(pc); jjg@283: if (list == null) { jjg@283: list = new ArrayList(); jjg@283: pcMap.put(pc, list); jjg@283: } jjg@283: if (!list.contains(entry)) jjg@283: list.add(entry); jjg@283: } jjg@283: jjg@283: private Map> pcMap; jjg@283: private Map indexMap; jjg@283: private ConstantWriter constantWriter; jjg@283: }