CodeWriter.java 9.9 KB
Newer Older
1
/*
X
xdono 已提交
2
 * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.javap;

28 29 30
import java.util.ArrayList;
import java.util.List;

31 32 33 34 35
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.DescriptorException;
36 37
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Instruction.TypeKind;
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
import com.sun.tools.classfile.Method;

/*
 *  Write the contents of a Code attribute.
 *
 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
 *  you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
class CodeWriter extends BasicWriter {
    static CodeWriter instance(Context context) {
        CodeWriter instance = context.get(CodeWriter.class);
        if (instance == null)
            instance = new CodeWriter(context);
        return instance;
    }

    protected CodeWriter(Context context) {
        super(context);
        context.put(CodeWriter.class, this);
        attrWriter = AttributeWriter.instance(context);
        classWriter = ClassWriter.instance(context);
        constantWriter = ConstantWriter.instance(context);
62 63 64 65 66
        sourceWriter = SourceWriter.instance(context);
        tryBlockWriter = TryBlockWriter.instance(context);
        stackMapWriter = StackMapWriter.instance(context);
        localVariableTableWriter = LocalVariableTableWriter.instance(context);
        localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
67
        typeAnnotationWriter = TypeAnnotationWriter.instance(context);
68
        options = Options.instance(context);
69 70 71
    }

    void write(Code_attribute attr, ConstantPool constant_pool) {
72 73
        println("Code:");
        indent(+1);
74 75 76 77
        writeVerboseHeader(attr, constant_pool);
        writeInstrs(attr);
        writeExceptionTable(attr);
        attrWriter.write(attr, attr.attributes, constant_pool);
78
        indent(-1);
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    }

    public void writeVerboseHeader(Code_attribute attr, ConstantPool constant_pool) {
        Method method = classWriter.getMethod();
        String argCount;
        try {
            int n = method.descriptor.getParameterCount(constant_pool);
            if (!method.access_flags.is(AccessFlags.ACC_STATIC))
                ++n;  // for 'this'
            argCount = Integer.toString(n);
        } catch (ConstantPoolException e) {
            argCount = report(e);
        } catch (DescriptorException e) {
            argCount = report(e);
        }

95 96 97
        println("stack=" + attr.max_stack +
                ", locals=" + attr.max_locals +
                ", args_size=" + argCount);
98 99 100 101

    }

    public void writeInstrs(Code_attribute attr) {
102 103
        List<InstructionDetailWriter> detailWriters = getDetailWriters(attr);

104 105
        for (Instruction instr: attr.getInstructions()) {
            try {
106 107
                for (InstructionDetailWriter w: detailWriters)
                    w.writeDetails(instr);
108 109 110 111
                writeInstr(instr);
            } catch (ArrayIndexOutOfBoundsException e) {
                println(report("error at or after byte " + instr.getPC()));
                break;
112 113
            }
        }
114 115 116

        for (InstructionDetailWriter w: detailWriters)
            w.flush();
117 118
    }

119
    public void writeInstr(Instruction instr) {
120
        print(String.format("%4d: %-13s ", instr.getPC(), instr.getMnemonic()));
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
        instr.accept(instructionPrinter, null);
        println();
    }
    // where
    Instruction.KindVisitor<Void,Void> instructionPrinter =
            new Instruction.KindVisitor<Void,Void>() {

        public Void visitNoOperands(Instruction instr, Void p) {
            return null;
        }

        public Void visitArrayType(Instruction instr, TypeKind kind, Void p) {
            print(" " + kind.name);
            return null;
        }

        public Void visitBranch(Instruction instr, int offset, Void p) {
138
            print((instr.getPC() + offset));
139 140 141 142
            return null;
        }

        public Void visitConstantPoolRef(Instruction instr, int index, Void p) {
143
            print("#" + index);
144 145
            tab();
            print("// ");
146 147 148 149 150
            printConstant(index);
            return null;
        }

        public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Void p) {
151
            print("#" + index + ",  " + value);
152 153
            tab();
            print("// ");
154 155 156 157 158
            printConstant(index);
            return null;
        }

        public Void visitLocal(Instruction instr, int index, Void p) {
159
            print(index);
160 161 162 163
            return null;
        }

        public Void visitLocalAndValue(Instruction instr, int index, int value, Void p) {
164
            print(index + ", " + value);
165 166 167 168 169
            return null;
        }

        public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets) {
            int pc = instr.getPC();
170 171
            print("{ // " + npairs);
            indent(+1);
172
            for (int i = 0; i < npairs; i++) {
173
                print("\n" + matches[i] + ": " + (pc + offsets[i]));
174
            }
175 176
            print("\ndefault: " + (pc + default_) + " }");
            indent(-1);
177
            return null;
178
        }
179 180 181 182

        public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets) {
            int pc = instr.getPC();
            print("{ //" + low + " to " + high);
183
            indent(+1);
184
            for (int i = 0; i < offsets.length; i++) {
185
                print("\n" + (low + i) + ": " + (pc + offsets[i]));
186
            }
187 188
            print("\ndefault: " + (pc + default_) + " }");
            indent(-1);
189
            return null;
190
        }
191 192

        public Void visitValue(Instruction instr, int value, Void p) {
193
            print(value);
194
            return null;
195
        }
196 197 198

        public Void visitUnknown(Instruction instr, Void p) {
            return null;
199
        }
200 201
    };

202 203 204

    public void writeExceptionTable(Code_attribute attr) {
        if (attr.exception_table_langth > 0) {
205 206 207
            println("Exception table:");
            indent(+1);
            println(" from    to  target type");
208 209
            for (int i = 0; i < attr.exception_table.length; i++) {
                Code_attribute.Exception_data handler = attr.exception_table[i];
210 211
                print(String.format(" %5d %5d %5d",
                        handler.start_pc, handler.end_pc, handler.handler_pc));
212 213 214 215 216 217 218 219 220
                print("   ");
                int catch_type = handler.catch_type;
                if (catch_type == 0) {
                    println("any");
                } else {
                    print("Class ");
                    println(constantWriter.stringValue(catch_type));
                }
            }
221
            indent(-1);
222 223 224 225 226 227 228 229
        }

    }

    private void printConstant(int index) {
        constantWriter.write(index);
    }

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    private List<InstructionDetailWriter> getDetailWriters(Code_attribute attr) {
        List<InstructionDetailWriter> detailWriters =
                new ArrayList<InstructionDetailWriter>();
        if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
            sourceWriter.reset(classWriter.getClassFile(), attr);
            detailWriters.add(sourceWriter);
        }

        if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {
            localVariableTableWriter.reset(attr);
            detailWriters.add(localVariableTableWriter);
        }

        if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VAR_TYPES)) {
            localVariableTypeTableWriter.reset(attr);
            detailWriters.add(localVariableTypeTableWriter);
        }

        if (options.details.contains(InstructionDetailWriter.Kind.STACKMAPS)) {
            stackMapWriter.reset(attr);
            stackMapWriter.writeInitialDetails();
            detailWriters.add(stackMapWriter);
        }

        if (options.details.contains(InstructionDetailWriter.Kind.TRY_BLOCKS)) {
            tryBlockWriter.reset(attr);
            detailWriters.add(tryBlockWriter);
        }

259 260 261 262 263
        if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) {
            typeAnnotationWriter.reset(attr);
            detailWriters.add(typeAnnotationWriter);
        }

264
        return detailWriters;
265 266 267 268 269
    }

    private AttributeWriter attrWriter;
    private ClassWriter classWriter;
    private ConstantWriter constantWriter;
270 271
    private LocalVariableTableWriter localVariableTableWriter;
    private LocalVariableTypeTableWriter localVariableTypeTableWriter;
272
    private TypeAnnotationWriter typeAnnotationWriter;
273 274 275 276
    private SourceWriter sourceWriter;
    private StackMapWriter stackMapWriter;
    private TryBlockWriter tryBlockWriter;
    private Options options;
277
}