NashornTextifier.java revision 1298:776551a5b3a2
11541Srgrimes/*
21541Srgrimes * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
31541Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41541Srgrimes *
51541Srgrimes * This code is free software; you can redistribute it and/or modify it
61541Srgrimes * under the terms of the GNU General Public License version 2 only, as
71541Srgrimes * published by the Free Software Foundation.  Oracle designates this
81541Srgrimes * particular file as subject to the "Classpath" exception as provided
91541Srgrimes * by Oracle in the LICENSE file that accompanied this code.
101541Srgrimes *
111541Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
121541Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131541Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141541Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
151541Srgrimes * accompanied this code).
161541Srgrimes *
171541Srgrimes * You should have received a copy of the GNU General Public License version
181541Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
191541Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
201541Srgrimes *
211541Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
221541Srgrimes * or visit www.oracle.com if you need additional information or have any
231541Srgrimes * questions.
241541Srgrimes */
251541Srgrimes
261541Srgrimespackage jdk.nashorn.internal.ir.debug;
271541Srgrimes
281541Srgrimesimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
2914505Shsuimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.FLAGS_MASK;
3050477Speter
311541Srgrimesimport java.io.File;
321541Srgrimesimport java.io.FileNotFoundException;
332165Spaulimport java.io.FileOutputStream;
342165Spaulimport java.io.PrintWriter;
352165Spaulimport java.util.HashMap;
3615492Sbdeimport java.util.HashSet;
3770834Swollmanimport java.util.Iterator;
38130380Srwatsonimport java.util.LinkedHashSet;
39130380Srwatsonimport java.util.List;
401541Srgrimesimport java.util.Map;
411541Srgrimesimport java.util.Set;
421541Srgrimesimport jdk.internal.org.objectweb.asm.Attribute;
431541Srgrimesimport jdk.internal.org.objectweb.asm.Handle;
441541Srgrimesimport jdk.internal.org.objectweb.asm.Label;
451541Srgrimesimport jdk.internal.org.objectweb.asm.Opcodes;
461541Srgrimesimport jdk.internal.org.objectweb.asm.Type;
4736079Swollmanimport jdk.internal.org.objectweb.asm.signature.SignatureReader;
4836079Swollmanimport jdk.internal.org.objectweb.asm.util.Printer;
49129958Srwatsonimport jdk.internal.org.objectweb.asm.util.TraceSignatureVisitor;
50129958Srwatsonimport jdk.nashorn.internal.runtime.ScriptEnvironment;
51129958Srwatsonimport jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
52129958Srwatson
53129958Srwatson/**
54129958Srwatson * Pretty printer for --print-code.
55129958Srwatson * Also supports dot formats if --print-code has arguments
56129958Srwatson */
57129958Srwatsonpublic final class NashornTextifier extends Printer {
58131168Srwatson
5995552Stanimura    private String currentClassName;
601541Srgrimes    private Iterator<Label> labelIter;
61130387Srwatson    private Graph graph;
62129958Srwatson    private String currentBlock;
6397658Stanimura
6497658Stanimura    // Following variables are used to govern the state of collapsing long sequences of NOP.
65130818Srwatson    /** True if the last instruction was a NOP. */
66129979Srwatson    private boolean lastWasNop = false;
6798993Salfred    /** True if ellipse ("...") was emitted in place of a second NOP. */
68129958Srwatson    private boolean lastWasEllipse = false;
691541Srgrimes
7013765Smpp    private static final int INTERNAL_NAME = 0;
711541Srgrimes    private static final int FIELD_DESCRIPTOR = 1;
721541Srgrimes    private static final int FIELD_SIGNATURE = 2;
7378913Sjlemon    private static final int METHOD_DESCRIPTOR = 3;
7478913Sjlemon    private static final int METHOD_SIGNATURE = 4;
751541Srgrimes    private static final int CLASS_SIGNATURE = 5;
7678913Sjlemon
771541Srgrimes    private final String tab = "  ";
781541Srgrimes    private final String tab2 = "    ";
791541Srgrimes    private final String tab3 = "      ";
80129979Srwatson
81129979Srwatson    private Map<Label, String> labelNames;
82129979Srwatson
83129979Srwatson    private boolean localVarsStarted = false;
84140730Sglebius
85140730Sglebius    private NashornClassReader cr;
8618787Spst    private ScriptEnvironment env;
87140730Sglebius
88130527Srwatson    /**
89131029Srwatson     * Constructs a new {@link NashornTextifier}. <i>Subclasses must not use this
9097658Stanimura     * constructor</i>. Instead, they must use the {@link #NashornTextifier(int)}
9141087Struckman     * version.
92131017Srwatson     * @param env script environment
9397658Stanimura     * @param cr a customized classreader for gathering, among other things, label
941541Srgrimes     * information
951541Srgrimes     */
961541Srgrimes    public NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr) {
9783421Sobrien        this(Opcodes.ASM5);
98100591Sjdp        this.env = env;
99130380Srwatson        this.cr = cr;
100141052Sglebius    }
101117708Srobert
102130527Srwatson    private NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr, final Iterator<Label> labelIter, final Graph graph) {
103130527Srwatson        this(env, cr);
104130527Srwatson        this.labelIter = labelIter;
105130527Srwatson        this.graph = graph;
106130527Srwatson    }
107130527Srwatson
108130527Srwatson    /**
109130527Srwatson     * Constructs a new {@link NashornTextifier}.
110130527Srwatson     *
111130527Srwatson     * @param api
112130527Srwatson     *            the ASM API version implemented by this visitor. Must be one
113130527Srwatson     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
1141541Srgrimes     */
115130818Srwatson    protected NashornTextifier(final int api) {
116130818Srwatson        super(api);
117130818Srwatson    }
1181541Srgrimes
119131022Srwatson    @Override
120131022Srwatson    public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
121131022Srwatson        final int major = version & 0xFFFF;
1221541Srgrimes        final int minor = version >>> 16;
1231541Srgrimes
1241541Srgrimes        currentClassName = name;
1251541Srgrimes
1261541Srgrimes        final StringBuilder sb = new StringBuilder();
12736527Speter        sb.append("// class version ").
1281541Srgrimes            append(major).
12955943Sjasone            append('.').
13059288Sjlemon            append(minor).append(" (").
1311541Srgrimes            append(version).
13297658Stanimura            append(")\n");
13397658Stanimura
134130527Srwatson        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
135130398Srwatson            sb.append("// DEPRECATED\n");
136130398Srwatson        }
13738482Swollman
138131168Srwatson        sb.append("// access flags 0x"). //TODO TRANSLATE TO WHAT THEY MEAN
13997658Stanimura            append(Integer.toHexString(access).toUpperCase()).
14097658Stanimura            append('\n');
14197658Stanimura
14297658Stanimura        appendDescriptor(sb, CLASS_SIGNATURE, signature);
14397658Stanimura        if (signature != null) {
14497658Stanimura            final TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
1451541Srgrimes            final SignatureReader r = new SignatureReader(signature);
1461541Srgrimes            r.accept(sv);
147121628Ssam            sb.append("// declaration: ").
148121628Ssam                append(name).
149121628Ssam                append(sv.getDeclaration()).
150121628Ssam                append('\n');
151121628Ssam        }
152121628Ssam
153121628Ssam        appendAccess(sb, access & ~Opcodes.ACC_SUPER);
1541541Srgrimes        if ((access & Opcodes.ACC_ANNOTATION) != 0) {
155129979Srwatson            sb.append("@interface ");
156129979Srwatson        } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
157129979Srwatson            sb.append("interface ");
158129979Srwatson        } else if ((access & Opcodes.ACC_ENUM) == 0) {
159129979Srwatson            sb.append("class ");
160129979Srwatson        }
161136682Srwatson        appendDescriptor(sb, INTERNAL_NAME, name);
162136682Srwatson
163130364Srwatson        if (superName != null && !"java/lang/Object".equals(superName)) {
164130364Srwatson            sb.append(" extends ");
165129979Srwatson            appendDescriptor(sb, INTERNAL_NAME, superName);
166129979Srwatson            sb.append(' ');
167130380Srwatson        }
168130380Srwatson        if (interfaces != null && interfaces.length > 0) {
169130380Srwatson            sb.append(" implements ");
170130380Srwatson            for (final String interface1 : interfaces) {
171130380Srwatson                appendDescriptor(sb, INTERNAL_NAME, interface1);
172130380Srwatson                sb.append(' ');
173130380Srwatson            }
174130380Srwatson        }
175130380Srwatson        sb.append(" {\n");
176130380Srwatson
177130380Srwatson        addText(sb);
178136326Srwatson    }
179130380Srwatson
180130380Srwatson    @Override
181130380Srwatson    public void visitSource(final String file, final String debug) {
182130380Srwatson        final StringBuilder sb = new StringBuilder();
183130380Srwatson        if (file != null) {
184130380Srwatson            sb.append(tab).
185130380Srwatson                append("// compiled from: ").
186130380Srwatson                append(file).
187130380Srwatson                append('\n');
188130380Srwatson        }
189130380Srwatson        if (debug != null) {
190130380Srwatson            sb.append(tab).
191130492Srwatson                append("// debug info: ").
1921541Srgrimes                append(debug).
193130480Srwatson                append('\n');
194130480Srwatson        }
195130480Srwatson        if (sb.length() > 0) {
196130480Srwatson            addText(sb);
197130480Srwatson        }
198130480Srwatson    }
199130480Srwatson
200130480Srwatson    @Override
201130480Srwatson    public void visitOuterClass(final String owner, final String name, final String desc) {
2021541Srgrimes        final StringBuilder sb = new StringBuilder();
20314547Sdg        sb.append(tab).append("outer class ");
20414547Sdg        appendDescriptor(sb, INTERNAL_NAME, owner);
20514547Sdg        sb.append(' ');
20614547Sdg        if (name != null) {
20714547Sdg            sb.append(name).append(' ');
20814547Sdg        }
20914547Sdg        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
21043196Sfenner        sb.append('\n');
2111541Srgrimes        addText(sb);
21236079Swollman    }
213130480Srwatson
214130480Srwatson    @Override
215130480Srwatson    public NashornTextifier visitField(final int access, final String name, final String desc, final String signature, final Object value) {
216130480Srwatson        final StringBuilder sb = new StringBuilder();
217130480Srwatson//        sb.append('\n');
218130480Srwatson        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
219130480Srwatson            sb.append(tab).append("// DEPRECATED\n");
220129916Srwatson        }
221129916Srwatson
222129916Srwatson/*        sb.append(tab).
223129916Srwatson            append("// access flags 0x").
224129916Srwatson            append(Integer.toHexString(access).toUpperCase()).
225129916Srwatson            append('\n');
22636079Swollman*/
22736079Swollman
22883045Sobrien        if (signature != null) {
22936079Swollman            sb.append(tab);
23036079Swollman            appendDescriptor(sb, FIELD_SIGNATURE, signature);
23136079Swollman
23236079Swollman            final TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
23336079Swollman            final SignatureReader r = new SignatureReader(signature);
23436079Swollman            r.acceptType(sv);
23536079Swollman            sb.append(tab).
23636079Swollman                append("// declaration: ").
23736079Swollman                append(sv.getDeclaration()).
238140730Sglebius                append('\n');
239140730Sglebius        }
240140730Sglebius
24136079Swollman        sb.append(tab);
24236079Swollman        appendAccess(sb, access);
24336079Swollman
24436079Swollman        final String prunedDesc = desc.endsWith(";") ? desc.substring(0, desc.length() - 1) : desc;
24583421Sobrien        appendDescriptor(sb, FIELD_DESCRIPTOR, prunedDesc);
246100591Sjdp        sb.append(' ').append(name);
247100591Sjdp        if (value != null) {
248100591Sjdp            sb.append(" = ");
249100591Sjdp            if (value instanceof String) {
250100591Sjdp                sb.append('\"').append(value).append('\"');
251100591Sjdp            } else {
25236079Swollman                sb.append(value);
25336079Swollman            }
25436079Swollman        }
25536079Swollman
25614547Sdg        sb.append(";\n");
257130393Srwatson        addText(sb);
258130393Srwatson
2591541Srgrimes        final NashornTextifier t = createNashornTextifier();
2601541Srgrimes        addText(t.getText());
2611541Srgrimes
2621541Srgrimes        return t;
2631541Srgrimes    }
26436527Speter
26536527Speter    @Override
26655943Sjasone    public NashornTextifier visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
26759288Sjlemon
26836527Speter        graph = new Graph(name);
26936527Speter
2701541Srgrimes        final List<Label> extraLabels = cr.getExtraLabels(currentClassName, name, desc);
2711541Srgrimes        this.labelIter = extraLabels == null ? null : extraLabels.iterator();
2721541Srgrimes
2731541Srgrimes        final StringBuilder sb = new StringBuilder();
2741541Srgrimes
2751541Srgrimes        sb.append('\n');
2761541Srgrimes        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
2771541Srgrimes            sb.append(tab).
2781541Srgrimes                append("// DEPRECATED\n");
2791541Srgrimes        }
2801541Srgrimes
2811541Srgrimes        sb.append(tab).
2821541Srgrimes            append("// access flags 0x").
2831541Srgrimes            append(Integer.toHexString(access).toUpperCase()).
2841541Srgrimes            append('\n');
2851541Srgrimes
286130480Srwatson        if (signature != null) {
28770536Sphk            sb.append(tab);
2881541Srgrimes            appendDescriptor(sb, METHOD_SIGNATURE, signature);
2891541Srgrimes
2901541Srgrimes            final TraceSignatureVisitor v = new TraceSignatureVisitor(0);
2913304Sphk            final SignatureReader r = new SignatureReader(signature);
2921541Srgrimes            r.accept(v);
2933304Sphk            final String genericDecl = v.getDeclaration();
294130480Srwatson            final String genericReturn = v.getReturnType();
2951541Srgrimes            final String genericExceptions = v.getExceptions();
2961541Srgrimes
2971541Srgrimes            sb.append(tab).
2981541Srgrimes                append("// declaration: ").
2991541Srgrimes                append(genericReturn).
300109098Stjr                append(' ').
301109098Stjr                append(name).
302106313Skbyanc                append(genericDecl);
3031541Srgrimes
3041541Srgrimes            if (genericExceptions != null) {
3051541Srgrimes                sb.append(" throws ").append(genericExceptions);
3061541Srgrimes            }
3071541Srgrimes            sb.append('\n');
3081541Srgrimes        }
3091541Srgrimes
3101541Srgrimes        sb.append(tab);
311109098Stjr        appendAccess(sb, access);
312109098Stjr        if ((access & Opcodes.ACC_NATIVE) != 0) {
313106313Skbyanc            sb.append("native ");
3141541Srgrimes        }
3151541Srgrimes        if ((access & Opcodes.ACC_VARARGS) != 0) {
3161541Srgrimes            sb.append("varargs ");
3171541Srgrimes        }
3181541Srgrimes        if ((access & Opcodes.ACC_BRIDGE) != 0) {
3191541Srgrimes            sb.append("bridge ");
3201541Srgrimes        }
3211541Srgrimes
3221541Srgrimes        sb.append(name);
3231541Srgrimes        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
3241541Srgrimes        if (exceptions != null && exceptions.length > 0) {
325111119Simp            sb.append(" throws ");
3261541Srgrimes            for (final String exception : exceptions) {
3271541Srgrimes                appendDescriptor(sb, INTERNAL_NAME, exception);
3281541Srgrimes                sb.append(' ');
329130831Srwatson            }
330130831Srwatson        }
3311541Srgrimes
3321541Srgrimes        sb.append('\n');
3331541Srgrimes        addText(sb);
334111748Sdes
3351541Srgrimes        final NashornTextifier t = createNashornTextifier();
336130831Srwatson        addText(t.getText());
3371541Srgrimes        return t;
33886487Sdillon    }
33986487Sdillon
34086487Sdillon    @Override
34186487Sdillon    public void visitClassEnd() {
34286487Sdillon        addText("}\n");
343130383Srwatson    }
344130387Srwatson
345130383Srwatson    @Override
346130383Srwatson    public void visitFieldEnd() {
34786487Sdillon        //empty
348130383Srwatson    }
349136682Srwatson
350130387Srwatson    @Override
351130383Srwatson    public void visitParameter(final String name, final int access) {
352130383Srwatson        final StringBuilder sb = new StringBuilder();
353130383Srwatson        sb.append(tab2).append("// parameter ");
354130383Srwatson        appendAccess(sb, access);
355136682Srwatson        sb.append(' ').append(name == null ? "<no name>" : name)
356130387Srwatson                .append('\n');
357136682Srwatson        addText(sb);
358136682Srwatson    }
359130383Srwatson
36086487Sdillon    @Override
361130383Srwatson    public void visitCode() {
362136682Srwatson        //empty
363130387Srwatson    }
364130383Srwatson
365130383Srwatson    @Override
366136682Srwatson    public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
367130387Srwatson        final StringBuilder sb = new StringBuilder();
368136682Srwatson        sb.append("frame ");
369136682Srwatson        switch (type) {
370130383Srwatson        case Opcodes.F_NEW:
37186487Sdillon        case Opcodes.F_FULL:
372130831Srwatson            sb.append("full [");
373130831Srwatson            appendFrameTypes(sb, nLocal, local);
374130831Srwatson            sb.append("] [");
375130831Srwatson            appendFrameTypes(sb, nStack, stack);
376130831Srwatson            sb.append(']');
377130831Srwatson            break;
378130831Srwatson        case Opcodes.F_APPEND:
379130831Srwatson            sb.append("append [");
380130831Srwatson            appendFrameTypes(sb, nLocal, local);
381130831Srwatson            sb.append(']');
382130383Srwatson            break;
383130831Srwatson        case Opcodes.F_CHOP:
384130831Srwatson            sb.append("chop ").append(nLocal);
385130831Srwatson            break;
386130383Srwatson        case Opcodes.F_SAME:
3871541Srgrimes            sb.append("same");
388130831Srwatson            break;
389130831Srwatson        case Opcodes.F_SAME1:
390130831Srwatson            sb.append("same1 ");
391130831Srwatson            appendFrameTypes(sb, 1, stack);
392130831Srwatson            break;
393130831Srwatson        default:
394131029Srwatson            assert false;
395130383Srwatson            break;
396130383Srwatson        }
397130831Srwatson        sb.append('\n');
398130831Srwatson        sb.append('\n');
399130383Srwatson        addText(sb);
4001541Srgrimes    }
401130831Srwatson
402130831Srwatson    private StringBuilder appendOpcode(final StringBuilder sb, final int opcode) {
403130831Srwatson        final Label next = getNextLabel();
404130831Srwatson        if (next instanceof NashornLabel) {
405130831Srwatson            final int bci = next.getOffset();
40638482Swollman            if (bci != -1) {
40738482Swollman                final String bcis = "" + bci;
40838482Swollman                for (int i = 0; i < 5 - bcis.length(); i++) {
40938482Swollman                    sb.append(' ');
41038482Swollman                }
41138482Swollman                sb.append(bcis);
41238482Swollman                sb.append(' ');
41338482Swollman            } else {
41438482Swollman                sb.append("       ");
41538482Swollman            }
41638482Swollman        }
41795959Salfred
41838482Swollman        return sb.append(tab2).append(OPCODES[opcode].toLowerCase());
41938482Swollman    }
42061837Salfred
42161837Salfred    private Label getNextLabel() {
42261837Salfred        return labelIter == null ? null : labelIter.next();
42392719Salfred    }
42461837Salfred
42592719Salfred    @Override
42661837Salfred    public void visitInsn(final int opcode) {
42792719Salfred        if(opcode == Opcodes.NOP) {
42895959Salfred            if(lastWasEllipse) {
42982656Sjlemon                getNextLabel();
43061837Salfred                return;
43131927Sbde            } else if(lastWasNop) {
43295959Salfred                getNextLabel();
43331927Sbde                addText("          ...\n");
43431927Sbde                lastWasEllipse = true;
43531927Sbde                return;
43631927Sbde            } else {
43795959Salfred                lastWasNop = true;
4382112Swollman            }
43995959Salfred        } else {
44036079Swollman            lastWasNop = lastWasEllipse = false;
44114505Shsu        }
44215492Sbde        final StringBuilder sb = new StringBuilder();
44315492Sbde        appendOpcode(sb, opcode).append('\n');
44432995Sbde        addText(sb);
44532995Sbde        checkNoFallThru(opcode, null);
44615492Sbde    }
4471541Srgrimes
4483304Sphk    @Override
4493304Sphk    public void visitIntInsn(final int opcode, final int operand) {
450142058Srwatson        final StringBuilder sb = new StringBuilder();
451132060Sdwmalone        appendOpcode(sb, opcode)
452132060Sdwmalone                .append(' ')
45392719Salfred                .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
45492719Salfred                        .toString(operand)).append('\n');
45592719Salfred        addText(sb);
456130831Srwatson    }
457121628Ssam
458130831Srwatson    @Override
459130050Srwatson    public void visitVarInsn(final int opcode, final int var) {
46092719Salfred        final StringBuilder sb = new StringBuilder();
461130831Srwatson        appendOpcode(sb, opcode).append(' ').append(var).append('\n');
462130831Srwatson        addText(sb);
46392719Salfred    }
46492719Salfred
465130831Srwatson    @Override
466130831Srwatson    public void visitTypeInsn(final int opcode, final String type) {
46792719Salfred        final StringBuilder sb = new StringBuilder();
468130831Srwatson        appendOpcode(sb, opcode).append(' ');
46992719Salfred        appendDescriptor(sb, INTERNAL_NAME, type);
47092719Salfred        sb.append('\n');
47119670Sbde        addText(sb);
47292719Salfred    }
47392719Salfred
474130831Srwatson    @Override
47592719Salfred    public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
476130831Srwatson        final StringBuilder sb = new StringBuilder();
47792719Salfred        appendOpcode(sb, opcode).append(' ');
478130831Srwatson        appendDescriptor(sb, INTERNAL_NAME, owner);
47992719Salfred        sb.append('.').append(name).append(" : ");
480130831Srwatson        appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
48192719Salfred        sb.append('\n');
482130831Srwatson        addText(sb);
48392719Salfred    }
48493008Sbde
485131006Srwatson    @Override
486131006Srwatson    public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
48792719Salfred        final StringBuilder sb = new StringBuilder();
48892719Salfred        appendOpcode(sb, opcode).append(' ');
48992719Salfred        appendDescriptor(sb, INTERNAL_NAME, owner);
49092719Salfred        sb.append('.').append(name);
49192719Salfred        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
492126411Srwatson        sb.append('\n');
49395959Salfred        addText(sb);
49492719Salfred    }
49592719Salfred
496130831Srwatson    @Override
49792719Salfred    public void visitInvokeDynamicInsn(final String name, final String desc, final Handle bsm, final Object... bsmArgs) {
498130831Srwatson        final StringBuilder sb = new StringBuilder();
49992719Salfred
50092719Salfred        appendOpcode(sb, Opcodes.INVOKEDYNAMIC).append(' ');
50192719Salfred        sb.append(name);
50298849Sken        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
50392719Salfred        final int len = sb.length();
50492719Salfred        for (int i = 0; i < 80 - len ; i++) {
505106326Salc            sb.append(' ');
50692719Salfred        }
507126425Srwatson        sb.append(" [");
50892719Salfred        appendHandle(sb, bsm);
50992719Salfred        if (bsmArgs.length == 0) {
51092719Salfred            sb.append("none");
51192719Salfred        } else {
51292719Salfred            for (final Object cst : bsmArgs) {
51392719Salfred                if (cst instanceof String) {
51492719Salfred                    appendStr(sb, (String)cst);
51592719Salfred                } else if (cst instanceof Type) {
516142190Srwatson                    sb.append(((Type)cst).getDescriptor()).append(".class");
517142190Srwatson                } else if (cst instanceof Handle) {
51814505Shsu                    appendHandle(sb, (Handle)cst);
51992719Salfred                } else if (cst instanceof Integer) {
52093008Sbde                    final int c = (Integer)cst;
521118453Shsu                    final int pp = c >> CALLSITE_PROGRAM_POINT_SHIFT;
52253541Sshin                    if (pp != 0) {
52353541Sshin                        sb.append(" pp=").append(pp);
52492719Salfred                    }
52592719Salfred                    sb.append(NashornCallSiteDescriptor.toString(c & FLAGS_MASK));
52692719Salfred                } else {
52753541Sshin                    sb.append(cst);
528101983Srwatson                }
52993008Sbde                sb.append(", ");
53093008Sbde            }
53193008Sbde            sb.setLength(sb.length() - 2);
53292719Salfred        }
53392719Salfred
53492719Salfred        sb.append("]\n");
53593008Sbde        addText(sb);
53693008Sbde    }
53792719Salfred
53892719Salfred    private static final boolean noFallThru(final int opcode) {
53992719Salfred        switch (opcode) {
54092719Salfred        case Opcodes.GOTO:
54131927Sbde        case Opcodes.ATHROW:
542121628Ssam        case Opcodes.ARETURN:
543121628Ssam        case Opcodes.IRETURN:
544121628Ssam        case Opcodes.LRETURN:
545121628Ssam        case Opcodes.FRETURN:
546121628Ssam        case Opcodes.DRETURN:
547121628Ssam            return true;
548121628Ssam        default:
549121628Ssam            return false;
550121628Ssam        }
551121628Ssam    }
552121628Ssam
55395959Salfred    private void checkNoFallThru(final int opcode, final String to) {
55495959Salfred        if (noFallThru(opcode)) {
55595959Salfred            graph.setNoFallThru(currentBlock);
55692719Salfred        }
55792719Salfred
55895959Salfred        if (currentBlock != null && to != null) {
55961837Salfred            graph.addEdge(currentBlock, to);
56095959Salfred        }
56165534Salfred    }
56295959Salfred
56395959Salfred    @Override
56495959Salfred    public void visitJumpInsn(final int opcode, final Label label) {
56561837Salfred        final StringBuilder sb = new StringBuilder();
56655205Speter        appendOpcode(sb, opcode).append(' ');
5672165Spaul        final String to = appendLabel(sb, label);
56814505Shsu        sb.append('\n');
569        addText(sb);
570        checkNoFallThru(opcode, to);
571    }
572
573    private void addText(final Object t) {
574        text.add(t);
575        if (currentBlock != null) {
576            graph.addText(currentBlock, t.toString());
577        }
578    }
579
580    @Override
581    public void visitLabel(final Label label) {
582        final StringBuilder sb = new StringBuilder();
583        sb.append("\n");
584        final String name = appendLabel(sb, label);
585        sb.append(" [bci=");
586        sb.append(label.info);
587        sb.append("]");
588        sb.append("\n");
589
590        graph.addNode(name);
591        if (currentBlock != null && !graph.isNoFallThru(currentBlock)) {
592            graph.addEdge(currentBlock, name);
593        }
594        currentBlock = name;
595        addText(sb);
596    }
597
598    @Override
599    public void visitLdcInsn(final Object cst) {
600        final StringBuilder sb = new StringBuilder();
601        appendOpcode(sb, Opcodes.LDC).append(' ');
602        if (cst instanceof String) {
603            appendStr(sb, (String) cst);
604        } else if (cst instanceof Type) {
605            sb.append(((Type) cst).getDescriptor()).append(".class");
606        } else {
607            sb.append(cst);
608        }
609        sb.append('\n');
610        addText(sb);
611    }
612
613    @Override
614    public void visitIincInsn(final int var, final int increment) {
615        final StringBuilder sb = new StringBuilder();
616        appendOpcode(sb, Opcodes.IINC).append(' ');
617        sb.append(var).append(' ')
618                .append(increment).append('\n');
619        addText(sb);
620    }
621
622    @Override
623    public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) {
624        final StringBuilder sb = new StringBuilder();
625        appendOpcode(sb, Opcodes.TABLESWITCH).append(' ');
626        for (int i = 0; i < labels.length; ++i) {
627            sb.append(tab3).append(min + i).append(": ");
628            final String to = appendLabel(sb, labels[i]);
629            graph.addEdge(currentBlock, to);
630            sb.append('\n');
631        }
632        sb.append(tab3).append("default: ");
633        appendLabel(sb, dflt);
634        sb.append('\n');
635        addText(sb);
636    }
637
638    @Override
639    public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
640        final StringBuilder sb = new StringBuilder();
641        appendOpcode(sb, Opcodes.LOOKUPSWITCH).append(' ');
642        for (int i = 0; i < labels.length; ++i) {
643            sb.append(tab3).append(keys[i]).append(": ");
644            final String to = appendLabel(sb, labels[i]);
645            graph.addEdge(currentBlock, to);
646            sb.append('\n');
647        }
648        sb.append(tab3).append("default: ");
649        final String to = appendLabel(sb, dflt);
650        graph.addEdge(currentBlock, to);
651        sb.append('\n');
652        addText(sb.toString());
653    }
654
655    @Override
656    public void visitMultiANewArrayInsn(final String desc, final int dims) {
657        final StringBuilder sb = new StringBuilder();
658        appendOpcode(sb, Opcodes.MULTIANEWARRAY).append(' ');
659        appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
660        sb.append(' ').append(dims).append('\n');
661        addText(sb);
662    }
663
664    @Override
665    public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
666        final StringBuilder sb = new StringBuilder();
667        sb.append(tab2).append("try ");
668        final String from = appendLabel(sb, start);
669        sb.append(' ');
670        appendLabel(sb, end);
671        sb.append(' ');
672        final String to = appendLabel(sb, handler);
673        sb.append(' ');
674        appendDescriptor(sb, INTERNAL_NAME, type);
675        sb.append('\n');
676        addText(sb);
677        graph.setIsCatch(to, type);
678        graph.addTryCatch(from, to);
679    }
680
681    @Override
682    public void visitLocalVariable(final String name, final String desc,final String signature, final Label start, final Label end, final int index) {
683
684        final StringBuilder sb = new StringBuilder();
685        if (!localVarsStarted) {
686            text.add("\n");
687            localVarsStarted = true;
688            graph.addNode("vars");
689            currentBlock = "vars";
690        }
691
692        sb.append(tab2).append("local ").append(name).append(' ');
693        final int len = sb.length();
694        for (int i = 0; i < 25 - len; i++) {
695            sb.append(' ');
696        }
697        String label;
698
699        label = appendLabel(sb, start);
700        for (int i = 0; i < 5 - label.length(); i++) {
701            sb.append(' ');
702        }
703        label = appendLabel(sb, end);
704        for (int i = 0; i < 5 - label.length(); i++) {
705            sb.append(' ');
706        }
707
708        sb.append(index).append(tab2);
709
710        appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
711        sb.append('\n');
712
713        if (signature != null) {
714            sb.append(tab2);
715            appendDescriptor(sb, FIELD_SIGNATURE, signature);
716
717            final TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
718            final SignatureReader r = new SignatureReader(signature);
719            r.acceptType(sv);
720            sb.append(tab2).append("// declaration: ")
721                    .append(sv.getDeclaration()).append('\n');
722        }
723        addText(sb.toString());
724    }
725
726    @Override
727    public void visitLineNumber(final int line, final Label start) {
728        final StringBuilder sb = new StringBuilder();
729        sb.append("<line ");
730        sb.append(line);
731        sb.append(">\n");
732        addText(sb.toString());
733    }
734
735    @Override
736    public void visitMaxs(final int maxStack, final int maxLocals) {
737        final StringBuilder sb = new StringBuilder();
738        sb.append('\n');
739        sb.append(tab2).append("max stack  = ").append(maxStack);
740        sb.append(", max locals = ").append(maxLocals).append('\n');
741        addText(sb.toString());
742    }
743
744    private void printToDir(final Graph g) {
745        if (env._print_code_dir != null) {
746            final File dir = new File(env._print_code_dir);
747            if (!dir.exists() && !dir.mkdirs()) {
748                throw new RuntimeException(dir.toString());
749            }
750
751            File file;
752            int uniqueId = 0;
753            do {
754                final String fileName = g.getName() + (uniqueId == 0 ? "" : "_" + uniqueId) +  ".dot";
755                file = new File(dir, fileName);
756                uniqueId++;
757            } while (file.exists());
758
759            try (PrintWriter pw = new PrintWriter(new FileOutputStream(file))) {
760                pw.println(g);
761            } catch (final FileNotFoundException e) {
762                throw new RuntimeException(e);
763            }
764        }
765    }
766
767    @Override
768    public void visitMethodEnd() {
769        //here we need to do several bytecode guesses best upon the ldc instructions.
770        //for each instruction, assign bci. for an ldc/w/2w, guess a byte and keep
771        //iterating. if the next label is wrong, backtrack.
772        if (env._print_code_func == null || env._print_code_func.equals(graph.getName())) {
773            if (env._print_code_dir != null) {
774                printToDir(graph);
775            }
776        }
777    }
778
779    /**
780     * Creates a new TraceVisitor instance.
781     *
782     * @return a new TraceVisitor.
783     */
784    protected NashornTextifier createNashornTextifier() {
785        return new NashornTextifier(env, cr, labelIter, graph);
786    }
787
788    private static void appendDescriptor(final StringBuilder sb, final int type, final String desc) {
789        if (desc != null) {
790            if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE || type == METHOD_SIGNATURE) {
791                sb.append("// signature ").append(desc).append('\n');
792            } else {
793                appendShortDescriptor(sb, desc);
794            }
795        }
796    }
797
798    private String appendLabel(final StringBuilder sb, final Label l) {
799        if (labelNames == null) {
800            labelNames = new HashMap<>();
801        }
802        String name = labelNames.get(l);
803        if (name == null) {
804            name = "L" + labelNames.size();
805            labelNames.put(l, name);
806        }
807        sb.append(name);
808        return name;
809    }
810
811    private static void appendHandle(final StringBuilder sb, final Handle h) {
812        switch (h.getTag()) {
813        case Opcodes.H_GETFIELD:
814            sb.append("getfield");
815            break;
816        case Opcodes.H_GETSTATIC:
817            sb.append("getstatic");
818            break;
819        case Opcodes.H_PUTFIELD:
820            sb.append("putfield");
821            break;
822        case Opcodes.H_PUTSTATIC:
823            sb.append("putstatic");
824            break;
825        case Opcodes.H_INVOKEINTERFACE:
826            sb.append("interface");
827            break;
828        case Opcodes.H_INVOKESPECIAL:
829            sb.append("special");
830            break;
831        case Opcodes.H_INVOKESTATIC:
832            sb.append("static");
833            break;
834        case Opcodes.H_INVOKEVIRTUAL:
835            sb.append("virtual");
836            break;
837        case Opcodes.H_NEWINVOKESPECIAL:
838            sb.append("new_special");
839            break;
840        default:
841            assert false;
842            break;
843        }
844        sb.append(" '");
845        sb.append(h.getName());
846        sb.append("'");
847    }
848
849    private static void appendAccess(final StringBuilder sb, final int access) {
850        if ((access & Opcodes.ACC_PUBLIC) != 0) {
851            sb.append("public ");
852        }
853        if ((access & Opcodes.ACC_PRIVATE) != 0) {
854            sb.append("private ");
855        }
856        if ((access & Opcodes.ACC_PROTECTED) != 0) {
857            sb.append("protected ");
858        }
859        if ((access & Opcodes.ACC_FINAL) != 0) {
860            sb.append("final ");
861        }
862        if ((access & Opcodes.ACC_STATIC) != 0) {
863            sb.append("static ");
864        }
865        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
866            sb.append("synchronized ");
867        }
868        if ((access & Opcodes.ACC_VOLATILE) != 0) {
869            sb.append("volatile ");
870        }
871        if ((access & Opcodes.ACC_TRANSIENT) != 0) {
872            sb.append("transient ");
873        }
874        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
875            sb.append("abstract ");
876        }
877        if ((access & Opcodes.ACC_STRICT) != 0) {
878            sb.append("strictfp ");
879        }
880        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
881            sb.append("synthetic ");
882        }
883        if ((access & Opcodes.ACC_MANDATED) != 0) {
884            sb.append("mandated ");
885        }
886        if ((access & Opcodes.ACC_ENUM) != 0) {
887            sb.append("enum ");
888        }
889    }
890
891    private void appendFrameTypes(final StringBuilder sb, final int n, final Object[] o) {
892        for (int i = 0; i < n; ++i) {
893            if (i > 0) {
894                sb.append(' ');
895            }
896            if (o[i] instanceof String) {
897                final String desc = (String) o[i];
898                if (desc.startsWith("[")) {
899                    appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
900                } else {
901                    appendDescriptor(sb, INTERNAL_NAME, desc);
902                }
903            } else if (o[i] instanceof Integer) {
904                switch (((Integer)o[i]).intValue()) {
905                case 0:
906                    appendDescriptor(sb, FIELD_DESCRIPTOR, "T");
907                    break;
908                case 1:
909                    appendDescriptor(sb, FIELD_DESCRIPTOR, "I");
910                    break;
911                case 2:
912                    appendDescriptor(sb, FIELD_DESCRIPTOR, "F");
913                    break;
914                case 3:
915                    appendDescriptor(sb, FIELD_DESCRIPTOR, "D");
916                    break;
917                case 4:
918                    appendDescriptor(sb, FIELD_DESCRIPTOR, "J");
919                    break;
920                case 5:
921                    appendDescriptor(sb, FIELD_DESCRIPTOR, "N");
922                    break;
923                case 6:
924                    appendDescriptor(sb, FIELD_DESCRIPTOR, "U");
925                    break;
926                default:
927                    assert false;
928                    break;
929                }
930            } else {
931                appendLabel(sb, (Label) o[i]);
932            }
933        }
934    }
935
936    private static void appendShortDescriptor(final StringBuilder sb, final String desc) {
937        //final StringBuilder buf = new StringBuilder();
938        if (desc.charAt(0) == '(') {
939            for (int i = 0; i < desc.length(); i++) {
940                if (desc.charAt(i) == 'L') {
941                    int slash = i;
942                    while (desc.charAt(i) != ';') {
943                        i++;
944                        if (desc.charAt(i) == '/') {
945                            slash = i;
946                        }
947                    }
948                    sb.append(desc.substring(slash + 1, i)).append(';');
949                } else {
950                    sb.append(desc.charAt(i));
951                }
952            }
953        } else {
954            final int lastSlash = desc.lastIndexOf('/');
955            final int lastBracket = desc.lastIndexOf('[');
956            if(lastBracket != -1) {
957                sb.append(desc, 0, lastBracket + 1);
958            }
959            sb.append(lastSlash == -1 ? desc : desc.substring(lastSlash + 1));
960        }
961    }
962
963    private static void appendStr(final StringBuilder sb, final String s) {
964        sb.append('\"');
965        for (int i = 0; i < s.length(); ++i) {
966            final char c = s.charAt(i);
967            if (c == '\n') {
968                sb.append("\\n");
969            } else if (c == '\r') {
970                sb.append("\\r");
971            } else if (c == '\\') {
972                sb.append("\\\\");
973            } else if (c == '"') {
974                sb.append("\\\"");
975            } else if (c < 0x20 || c > 0x7f) {
976                sb.append("\\u");
977                if (c < 0x10) {
978                    sb.append("000");
979                } else if (c < 0x100) {
980                    sb.append("00");
981                } else if (c < 0x1000) {
982                    sb.append('0');
983                }
984                sb.append(Integer.toString(c, 16));
985            } else {
986                sb.append(c);
987            }
988        }
989        sb.append('\"');
990    }
991
992    private static class Graph {
993        private final LinkedHashSet<String> nodes;
994        private final Map<String, StringBuilder> contents;
995        private final Map<String, Set<String>> edges;
996        private final Set<String> hasPreds;
997        private final Set<String> noFallThru;
998        private final Map<String, String> catches;
999        private final Map<String, Set<String>> exceptionMap; //maps catch nodes to all their trys that can reach them
1000        private final String name;
1001
1002        private static final String LEFT_ALIGN      = "\\l";
1003        private static final String COLOR_CATCH     = "\"#ee9999\"";
1004        private static final String COLOR_ORPHAN    = "\"#9999bb\"";
1005        private static final String COLOR_DEFAULT   = "\"#99bb99\"";
1006        private static final String COLOR_LOCALVARS = "\"#999999\"";
1007
1008        Graph(final String name) {
1009            this.name         = name;
1010            this.nodes        = new LinkedHashSet<>();
1011            this.contents     = new HashMap<>();
1012            this.edges        = new HashMap<>();
1013            this.hasPreds     = new HashSet<>();
1014            this.catches      = new HashMap<>();
1015            this.noFallThru   = new HashSet<>();
1016            this.exceptionMap = new HashMap<>();
1017         }
1018
1019        void addEdge(final String from, final String to) {
1020            Set<String> edgeSet = edges.get(from);
1021            if (edgeSet == null) {
1022                edgeSet = new LinkedHashSet<>();
1023                edges.put(from, edgeSet);
1024            }
1025            edgeSet.add(to);
1026            hasPreds.add(to);
1027        }
1028
1029        void addTryCatch(final String tryNode, final String catchNode) {
1030            Set<String> tryNodes = exceptionMap.get(catchNode);
1031            if (tryNodes == null) {
1032                tryNodes = new HashSet<>();
1033                exceptionMap.put(catchNode, tryNodes);
1034            }
1035            if (!tryNodes.contains(tryNode)) {
1036                addEdge(tryNode, catchNode);
1037            }
1038            tryNodes.add(tryNode);
1039        }
1040
1041        void addNode(final String node) {
1042            assert !nodes.contains(node);
1043            nodes.add(node);
1044        }
1045
1046        void setNoFallThru(final String node) {
1047            noFallThru.add(node);
1048        }
1049
1050        boolean isNoFallThru(final String node) {
1051            return noFallThru.contains(node);
1052        }
1053
1054        void setIsCatch(final String node, final String exception) {
1055            catches.put(node, exception);
1056        }
1057
1058        String getName() {
1059            return name;
1060        }
1061
1062        void addText(final String node, final String text) {
1063            StringBuilder sb = contents.get(node);
1064            if (sb == null) {
1065                sb = new StringBuilder();
1066            }
1067
1068            for (int i = 0; i < text.length(); i++) {
1069                switch (text.charAt(i)) {
1070                case '\n':
1071                    sb.append(LEFT_ALIGN);
1072                    break;
1073                case '"':
1074                    sb.append("'");
1075                    break;
1076                default:
1077                    sb.append(text.charAt(i));
1078                    break;
1079                }
1080           }
1081
1082            contents.put(node, sb);
1083        }
1084
1085        private static String dottyFriendly(final String name) {
1086            return name.replace(':', '_');
1087        }
1088
1089        @Override
1090        public String toString() {
1091
1092            final StringBuilder sb = new StringBuilder();
1093            sb.append("digraph " + dottyFriendly(name) + " {");
1094            sb.append("\n");
1095            sb.append("\tgraph [fontname=courier]\n");
1096            sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n");
1097            sb.append("\tedge [fontname=courier]\n\n");
1098
1099            for (final String node : nodes) {
1100                sb.append("\t");
1101                sb.append(node);
1102                sb.append(" [");
1103                sb.append("id=");
1104                sb.append(node);
1105                sb.append(", label=\"");
1106                String c = contents.get(node).toString();
1107                if (c.startsWith(LEFT_ALIGN)) {
1108                    c = c.substring(LEFT_ALIGN.length());
1109                }
1110                final String ex = catches.get(node);
1111                if (ex != null) {
1112                    sb.append("*** CATCH: ").append(ex).append(" ***\\l");
1113                }
1114                sb.append(c);
1115                sb.append("\"]\n");
1116            }
1117
1118            for (final String from : edges.keySet()) {
1119                for (final String to : edges.get(from)) {
1120                    sb.append("\t");
1121                    sb.append(from);
1122                    sb.append(" -> ");
1123                    sb.append(to);
1124                    sb.append("[label=\"");
1125                    sb.append(to);
1126                    sb.append("\"");
1127                    if (catches.get(to) != null) {
1128                        sb.append(", color=red, style=dashed");
1129                    }
1130                    sb.append(']');
1131                    sb.append(";\n");
1132                }
1133            }
1134
1135            sb.append("\n");
1136            for (final String node : nodes) {
1137                sb.append("\t");
1138                sb.append(node);
1139                sb.append(" [shape=box");
1140                if (catches.get(node) != null) {
1141                    sb.append(", color=" + COLOR_CATCH);
1142                } else if ("vars".equals(node)) {
1143                    sb.append(", shape=hexagon, color=" + COLOR_LOCALVARS);
1144                } else if (!hasPreds.contains(node)) {
1145                    sb.append(", color=" + COLOR_ORPHAN);
1146                }
1147                sb.append("]\n");
1148            }
1149
1150            sb.append("}\n");
1151            return sb.toString();
1152        }
1153    }
1154
1155    static class NashornLabel extends Label {
1156        final Label label;
1157        final int   bci;
1158        final int   opcode;
1159
1160        NashornLabel(final Label label, final int bci) {
1161            this.label = label;
1162            this.bci   = bci;
1163            this.opcode = -1;
1164        }
1165
1166        //not an ASM label
1167        NashornLabel(final int opcode, final int bci) {
1168            this.opcode = opcode;
1169            this.bci = bci;
1170            this.label = null;
1171        }
1172
1173        Label getLabel() {
1174            return label;
1175        }
1176
1177        @Override
1178        public int getOffset() {
1179            return bci;
1180        }
1181
1182        @Override
1183        public String toString() {
1184            return "label " + bci;
1185        }
1186    }
1187
1188    @Override
1189    public Printer visitAnnotationDefault() {
1190        throw new AssertionError();
1191    }
1192
1193    @Override
1194    public Printer visitClassAnnotation(final String arg0, final boolean arg1) {
1195        return this;
1196    }
1197
1198    @Override
1199    public void visitClassAttribute(final Attribute arg0) {
1200        throw new AssertionError();
1201    }
1202
1203    @Override
1204    public Printer visitFieldAnnotation(final String arg0, final boolean arg1) {
1205        throw new AssertionError();
1206    }
1207
1208    @Override
1209    public void visitFieldAttribute(final Attribute arg0) {
1210        throw new AssertionError();
1211    }
1212
1213    @Override
1214    public Printer visitMethodAnnotation(final String arg0, final boolean arg1) {
1215        return this;
1216    }
1217
1218    @Override
1219    public void visitMethodAttribute(final Attribute arg0) {
1220        throw new AssertionError();
1221    }
1222
1223    @Override
1224    public Printer visitParameterAnnotation(final int arg0, final String arg1, final boolean arg2) {
1225        throw new AssertionError();
1226    }
1227
1228    @Override
1229    public void visit(final String arg0, final Object arg1) {
1230        throw new AssertionError();
1231    }
1232
1233    @Override
1234    public Printer visitAnnotation(final String arg0, final String arg1) {
1235        throw new AssertionError();
1236    }
1237
1238    @Override
1239    public void visitAnnotationEnd() {
1240        //empty
1241    }
1242
1243    @Override
1244    public Printer visitArray(final String arg0) {
1245        throw new AssertionError();
1246    }
1247
1248    @Override
1249    public void visitEnum(final String arg0, final String arg1, final String arg2) {
1250        throw new AssertionError();
1251    }
1252
1253    @Override
1254    public void visitInnerClass(final String arg0, final String arg1, final String arg2, final int arg3) {
1255        throw new AssertionError();
1256    }
1257}
1258