diff options
Diffstat (limited to 'src/jdk/nashorn/internal/ir/debug/NashornTextifier.java')
-rw-r--r-- | src/jdk/nashorn/internal/ir/debug/NashornTextifier.java | 1257 |
1 files changed, 0 insertions, 1257 deletions
diff --git a/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java b/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java deleted file mode 100644 index c5dc56bf..00000000 --- a/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.ir.debug; - -import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; -import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.FLAGS_MASK; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import jdk.internal.org.objectweb.asm.Attribute; -import jdk.internal.org.objectweb.asm.Handle; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; -import jdk.internal.org.objectweb.asm.signature.SignatureReader; -import jdk.internal.org.objectweb.asm.util.Printer; -import jdk.internal.org.objectweb.asm.util.TraceSignatureVisitor; -import jdk.nashorn.internal.runtime.ScriptEnvironment; -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; - -/** - * Pretty printer for --print-code. - * Also supports dot formats if --print-code has arguments - */ -public final class NashornTextifier extends Printer { - - private String currentClassName; - private Iterator<Label> labelIter; - private Graph graph; - private String currentBlock; - - // Following variables are used to govern the state of collapsing long sequences of NOP. - /** True if the last instruction was a NOP. */ - private boolean lastWasNop = false; - /** True if ellipse ("...") was emitted in place of a second NOP. */ - private boolean lastWasEllipse = false; - - private static final int INTERNAL_NAME = 0; - private static final int FIELD_DESCRIPTOR = 1; - private static final int FIELD_SIGNATURE = 2; - private static final int METHOD_DESCRIPTOR = 3; - private static final int METHOD_SIGNATURE = 4; - private static final int CLASS_SIGNATURE = 5; - - private final String tab = " "; - private final String tab2 = " "; - private final String tab3 = " "; - - private Map<Label, String> labelNames; - - private boolean localVarsStarted = false; - - private NashornClassReader cr; - private ScriptEnvironment env; - - /** - * Constructs a new {@link NashornTextifier}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the {@link #NashornTextifier(int)} - * version. - * @param env script environment - * @param cr a customized classreader for gathering, among other things, label - * information - */ - public NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr) { - this(Opcodes.ASM5); - this.env = env; - this.cr = cr; - } - - private NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr, final Iterator<Label> labelIter, final Graph graph) { - this(env, cr); - this.labelIter = labelIter; - this.graph = graph; - } - - /** - * Constructs a new {@link NashornTextifier}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected NashornTextifier(final int api) { - super(api); - } - - @Override - public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { - final int major = version & 0xFFFF; - final int minor = version >>> 16; - - currentClassName = name; - - final StringBuilder sb = new StringBuilder(); - sb.append("// class version "). - append(major). - append('.'). - append(minor).append(" ("). - append(version). - append(")\n"); - - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - sb.append("// DEPRECATED\n"); - } - - sb.append("// access flags 0x"). //TODO TRANSLATE TO WHAT THEY MEAN - append(Integer.toHexString(access).toUpperCase()). - append('\n'); - - appendDescriptor(sb, CLASS_SIGNATURE, signature); - if (signature != null) { - final TraceSignatureVisitor sv = new TraceSignatureVisitor(access); - final SignatureReader r = new SignatureReader(signature); - r.accept(sv); - sb.append("// declaration: "). - append(name). - append(sv.getDeclaration()). - append('\n'); - } - - appendAccess(sb, access & ~Opcodes.ACC_SUPER); - if ((access & Opcodes.ACC_ANNOTATION) != 0) { - sb.append("@interface "); - } else if ((access & Opcodes.ACC_INTERFACE) != 0) { - sb.append("interface "); - } else if ((access & Opcodes.ACC_ENUM) == 0) { - sb.append("class "); - } - appendDescriptor(sb, INTERNAL_NAME, name); - - if (superName != null && !"java/lang/Object".equals(superName)) { - sb.append(" extends "); - appendDescriptor(sb, INTERNAL_NAME, superName); - sb.append(' '); - } - if (interfaces != null && interfaces.length > 0) { - sb.append(" implements "); - for (final String interface1 : interfaces) { - appendDescriptor(sb, INTERNAL_NAME, interface1); - sb.append(' '); - } - } - sb.append(" {\n"); - - addText(sb); - } - - @Override - public void visitSource(final String file, final String debug) { - final StringBuilder sb = new StringBuilder(); - if (file != null) { - sb.append(tab). - append("// compiled from: "). - append(file). - append('\n'); - } - if (debug != null) { - sb.append(tab). - append("// debug info: "). - append(debug). - append('\n'); - } - if (sb.length() > 0) { - addText(sb); - } - } - - @Override - public void visitOuterClass(final String owner, final String name, final String desc) { - final StringBuilder sb = new StringBuilder(); - sb.append(tab).append("outer class "); - appendDescriptor(sb, INTERNAL_NAME, owner); - sb.append(' '); - if (name != null) { - sb.append(name).append(' '); - } - appendDescriptor(sb, METHOD_DESCRIPTOR, desc); - sb.append('\n'); - addText(sb); - } - - @Override - public NashornTextifier visitField(final int access, final String name, final String desc, final String signature, final Object value) { - final StringBuilder sb = new StringBuilder(); -// sb.append('\n'); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - sb.append(tab).append("// DEPRECATED\n"); - } - -/* sb.append(tab). - append("// access flags 0x"). - append(Integer.toHexString(access).toUpperCase()). - append('\n'); -*/ - - if (signature != null) { - sb.append(tab); - appendDescriptor(sb, FIELD_SIGNATURE, signature); - - final TraceSignatureVisitor sv = new TraceSignatureVisitor(0); - final SignatureReader r = new SignatureReader(signature); - r.acceptType(sv); - sb.append(tab). - append("// declaration: "). - append(sv.getDeclaration()). - append('\n'); - } - - sb.append(tab); - appendAccess(sb, access); - - final String prunedDesc = desc.endsWith(";") ? desc.substring(0, desc.length() - 1) : desc; - appendDescriptor(sb, FIELD_DESCRIPTOR, prunedDesc); - sb.append(' ').append(name); - if (value != null) { - sb.append(" = "); - if (value instanceof String) { - sb.append('\"').append(value).append('\"'); - } else { - sb.append(value); - } - } - - sb.append(";\n"); - addText(sb); - - final NashornTextifier t = createNashornTextifier(); - addText(t.getText()); - - return t; - } - - @Override - public NashornTextifier visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { - - graph = new Graph(name); - - final List<Label> extraLabels = cr.getExtraLabels(currentClassName, name, desc); - this.labelIter = extraLabels == null ? null : extraLabels.iterator(); - - final StringBuilder sb = new StringBuilder(); - - sb.append('\n'); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - sb.append(tab). - append("// DEPRECATED\n"); - } - - sb.append(tab). - append("// access flags 0x"). - append(Integer.toHexString(access).toUpperCase()). - append('\n'); - - if (signature != null) { - sb.append(tab); - appendDescriptor(sb, METHOD_SIGNATURE, signature); - - final TraceSignatureVisitor v = new TraceSignatureVisitor(0); - final SignatureReader r = new SignatureReader(signature); - r.accept(v); - final String genericDecl = v.getDeclaration(); - final String genericReturn = v.getReturnType(); - final String genericExceptions = v.getExceptions(); - - sb.append(tab). - append("// declaration: "). - append(genericReturn). - append(' '). - append(name). - append(genericDecl); - - if (genericExceptions != null) { - sb.append(" throws ").append(genericExceptions); - } - sb.append('\n'); - } - - sb.append(tab); - appendAccess(sb, access); - if ((access & Opcodes.ACC_NATIVE) != 0) { - sb.append("native "); - } - if ((access & Opcodes.ACC_VARARGS) != 0) { - sb.append("varargs "); - } - if ((access & Opcodes.ACC_BRIDGE) != 0) { - sb.append("bridge "); - } - - sb.append(name); - appendDescriptor(sb, METHOD_DESCRIPTOR, desc); - if (exceptions != null && exceptions.length > 0) { - sb.append(" throws "); - for (final String exception : exceptions) { - appendDescriptor(sb, INTERNAL_NAME, exception); - sb.append(' '); - } - } - - sb.append('\n'); - addText(sb); - - final NashornTextifier t = createNashornTextifier(); - addText(t.getText()); - return t; - } - - @Override - public void visitClassEnd() { - addText("}\n"); - } - - @Override - public void visitFieldEnd() { - //empty - } - - @Override - public void visitParameter(final String name, final int access) { - final StringBuilder sb = new StringBuilder(); - sb.append(tab2).append("// parameter "); - appendAccess(sb, access); - sb.append(' ').append(name == null ? "<no name>" : name) - .append('\n'); - addText(sb); - } - - @Override - public void visitCode() { - //empty - } - - @Override - public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { - final StringBuilder sb = new StringBuilder(); - sb.append("frame "); - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - sb.append("full ["); - appendFrameTypes(sb, nLocal, local); - sb.append("] ["); - appendFrameTypes(sb, nStack, stack); - sb.append(']'); - break; - case Opcodes.F_APPEND: - sb.append("append ["); - appendFrameTypes(sb, nLocal, local); - sb.append(']'); - break; - case Opcodes.F_CHOP: - sb.append("chop ").append(nLocal); - break; - case Opcodes.F_SAME: - sb.append("same"); - break; - case Opcodes.F_SAME1: - sb.append("same1 "); - appendFrameTypes(sb, 1, stack); - break; - default: - assert false; - break; - } - sb.append('\n'); - sb.append('\n'); - addText(sb); - } - - private StringBuilder appendOpcode(final StringBuilder sb, final int opcode) { - final Label next = getNextLabel(); - if (next instanceof NashornLabel) { - final int bci = next.getOffset(); - if (bci != -1) { - final String bcis = "" + bci; - for (int i = 0; i < 5 - bcis.length(); i++) { - sb.append(' '); - } - sb.append(bcis); - sb.append(' '); - } else { - sb.append(" "); - } - } - - return sb.append(tab2).append(OPCODES[opcode].toLowerCase()); - } - - private Label getNextLabel() { - return labelIter == null ? null : labelIter.next(); - } - - @Override - public void visitInsn(final int opcode) { - if(opcode == Opcodes.NOP) { - if(lastWasEllipse) { - getNextLabel(); - return; - } else if(lastWasNop) { - getNextLabel(); - addText(" ...\n"); - lastWasEllipse = true; - return; - } else { - lastWasNop = true; - } - } else { - lastWasNop = lastWasEllipse = false; - } - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode).append('\n'); - addText(sb); - checkNoFallThru(opcode, null); - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode) - .append(' ') - .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer - .toString(operand)).append('\n'); - addText(sb); - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode).append(' ').append(var).append('\n'); - addText(sb); - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode).append(' '); - appendDescriptor(sb, INTERNAL_NAME, type); - sb.append('\n'); - addText(sb); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode).append(' '); - appendDescriptor(sb, INTERNAL_NAME, owner); - sb.append('.').append(name).append(" : "); - appendDescriptor(sb, FIELD_DESCRIPTOR, desc); - sb.append('\n'); - addText(sb); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode).append(' '); - appendDescriptor(sb, INTERNAL_NAME, owner); - sb.append('.').append(name); - appendDescriptor(sb, METHOD_DESCRIPTOR, desc); - sb.append('\n'); - addText(sb); - } - - @Override - public void visitInvokeDynamicInsn(final String name, final String desc, final Handle bsm, final Object... bsmArgs) { - final StringBuilder sb = new StringBuilder(); - - appendOpcode(sb, Opcodes.INVOKEDYNAMIC).append(' '); - sb.append(name); - appendDescriptor(sb, METHOD_DESCRIPTOR, desc); - final int len = sb.length(); - for (int i = 0; i < 80 - len ; i++) { - sb.append(' '); - } - sb.append(" ["); - appendHandle(sb, bsm); - if (bsmArgs.length == 0) { - sb.append("none"); - } else { - for (final Object cst : bsmArgs) { - if (cst instanceof String) { - appendStr(sb, (String)cst); - } else if (cst instanceof Type) { - sb.append(((Type)cst).getDescriptor()).append(".class"); - } else if (cst instanceof Handle) { - appendHandle(sb, (Handle)cst); - } else if (cst instanceof Integer) { - final int c = (Integer)cst; - final int pp = c >> CALLSITE_PROGRAM_POINT_SHIFT; - if (pp != 0) { - sb.append(" pp=").append(pp); - } - sb.append(NashornCallSiteDescriptor.toString(c & FLAGS_MASK)); - } else { - sb.append(cst); - } - sb.append(", "); - } - sb.setLength(sb.length() - 2); - } - - sb.append("]\n"); - addText(sb); - } - - private static final boolean noFallThru(final int opcode) { - switch (opcode) { - case Opcodes.GOTO: - case Opcodes.ATHROW: - case Opcodes.ARETURN: - case Opcodes.IRETURN: - case Opcodes.LRETURN: - case Opcodes.FRETURN: - case Opcodes.DRETURN: - return true; - default: - return false; - } - } - - private void checkNoFallThru(final int opcode, final String to) { - if (noFallThru(opcode)) { - graph.setNoFallThru(currentBlock); - } - - if (currentBlock != null && to != null) { - graph.addEdge(currentBlock, to); - } - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, opcode).append(' '); - final String to = appendLabel(sb, label); - sb.append('\n'); - addText(sb); - checkNoFallThru(opcode, to); - } - - private void addText(final Object t) { - text.add(t); - if (currentBlock != null) { - graph.addText(currentBlock, t.toString()); - } - } - - @Override - public void visitLabel(final Label label) { - final StringBuilder sb = new StringBuilder(); - sb.append("\n"); - final String name = appendLabel(sb, label); - sb.append(" [bci="); - sb.append(label.info); - sb.append("]"); - sb.append("\n"); - - graph.addNode(name); - if (currentBlock != null && !graph.isNoFallThru(currentBlock)) { - graph.addEdge(currentBlock, name); - } - currentBlock = name; - addText(sb); - } - - @Override - public void visitLdcInsn(final Object cst) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, Opcodes.LDC).append(' '); - if (cst instanceof String) { - appendStr(sb, (String) cst); - } else if (cst instanceof Type) { - sb.append(((Type) cst).getDescriptor()).append(".class"); - } else { - sb.append(cst); - } - sb.append('\n'); - addText(sb); - } - - @Override - public void visitIincInsn(final int var, final int increment) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, Opcodes.IINC).append(' '); - sb.append(var).append(' ') - .append(increment).append('\n'); - addText(sb); - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, Opcodes.TABLESWITCH).append(' '); - for (int i = 0; i < labels.length; ++i) { - sb.append(tab3).append(min + i).append(": "); - final String to = appendLabel(sb, labels[i]); - graph.addEdge(currentBlock, to); - sb.append('\n'); - } - sb.append(tab3).append("default: "); - appendLabel(sb, dflt); - sb.append('\n'); - addText(sb); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, Opcodes.LOOKUPSWITCH).append(' '); - for (int i = 0; i < labels.length; ++i) { - sb.append(tab3).append(keys[i]).append(": "); - final String to = appendLabel(sb, labels[i]); - graph.addEdge(currentBlock, to); - sb.append('\n'); - } - sb.append(tab3).append("default: "); - final String to = appendLabel(sb, dflt); - graph.addEdge(currentBlock, to); - sb.append('\n'); - addText(sb.toString()); - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - final StringBuilder sb = new StringBuilder(); - appendOpcode(sb, Opcodes.MULTIANEWARRAY).append(' '); - appendDescriptor(sb, FIELD_DESCRIPTOR, desc); - sb.append(' ').append(dims).append('\n'); - addText(sb); - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) { - final StringBuilder sb = new StringBuilder(); - sb.append(tab2).append("try "); - final String from = appendLabel(sb, start); - sb.append(' '); - appendLabel(sb, end); - sb.append(' '); - final String to = appendLabel(sb, handler); - sb.append(' '); - appendDescriptor(sb, INTERNAL_NAME, type); - sb.append('\n'); - addText(sb); - graph.setIsCatch(to, type); - graph.addTryCatch(from, to); - } - - @Override - public void visitLocalVariable(final String name, final String desc,final String signature, final Label start, final Label end, final int index) { - - final StringBuilder sb = new StringBuilder(); - if (!localVarsStarted) { - text.add("\n"); - localVarsStarted = true; - graph.addNode("vars"); - currentBlock = "vars"; - } - - sb.append(tab2).append("local ").append(name).append(' '); - final int len = sb.length(); - for (int i = 0; i < 25 - len; i++) { - sb.append(' '); - } - String label; - - label = appendLabel(sb, start); - for (int i = 0; i < 5 - label.length(); i++) { - sb.append(' '); - } - label = appendLabel(sb, end); - for (int i = 0; i < 5 - label.length(); i++) { - sb.append(' '); - } - - sb.append(index).append(tab2); - - appendDescriptor(sb, FIELD_DESCRIPTOR, desc); - sb.append('\n'); - - if (signature != null) { - sb.append(tab2); - appendDescriptor(sb, FIELD_SIGNATURE, signature); - - final TraceSignatureVisitor sv = new TraceSignatureVisitor(0); - final SignatureReader r = new SignatureReader(signature); - r.acceptType(sv); - sb.append(tab2).append("// declaration: ") - .append(sv.getDeclaration()).append('\n'); - } - addText(sb.toString()); - } - - @Override - public void visitLineNumber(final int line, final Label start) { - final StringBuilder sb = new StringBuilder(); - sb.append("<line "); - sb.append(line); - sb.append(">\n"); - addText(sb.toString()); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - final StringBuilder sb = new StringBuilder(); - sb.append('\n'); - sb.append(tab2).append("max stack = ").append(maxStack); - sb.append(", max locals = ").append(maxLocals).append('\n'); - addText(sb.toString()); - } - - private void printToDir(final Graph g) { - if (env._print_code_dir != null) { - final File dir = new File(env._print_code_dir); - if (!dir.exists() && !dir.mkdirs()) { - throw new RuntimeException(dir.toString()); - } - - File file; - int uniqueId = 0; - do { - final String fileName = g.getName() + (uniqueId == 0 ? "" : "_" + uniqueId) + ".dot"; - file = new File(dir, fileName); - uniqueId++; - } while (file.exists()); - - try (PrintWriter pw = new PrintWriter(new FileOutputStream(file))) { - pw.println(g); - } catch (final FileNotFoundException e) { - throw new RuntimeException(e); - } - } - } - - @Override - public void visitMethodEnd() { - //here we need to do several bytecode guesses best upon the ldc instructions. - //for each instruction, assign bci. for an ldc/w/2w, guess a byte and keep - //iterating. if the next label is wrong, backtrack. - if (env._print_code_func == null || env._print_code_func.equals(graph.getName())) { - if (env._print_code_dir != null) { - printToDir(graph); - } - } - } - - /** - * Creates a new TraceVisitor instance. - * - * @return a new TraceVisitor. - */ - protected NashornTextifier createNashornTextifier() { - return new NashornTextifier(env, cr, labelIter, graph); - } - - private static void appendDescriptor(final StringBuilder sb, final int type, final String desc) { - if (desc != null) { - if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE || type == METHOD_SIGNATURE) { - sb.append("// signature ").append(desc).append('\n'); - } else { - appendShortDescriptor(sb, desc); - } - } - } - - private String appendLabel(final StringBuilder sb, final Label l) { - if (labelNames == null) { - labelNames = new HashMap<>(); - } - String name = labelNames.get(l); - if (name == null) { - name = "L" + labelNames.size(); - labelNames.put(l, name); - } - sb.append(name); - return name; - } - - private static void appendHandle(final StringBuilder sb, final Handle h) { - switch (h.getTag()) { - case Opcodes.H_GETFIELD: - sb.append("getfield"); - break; - case Opcodes.H_GETSTATIC: - sb.append("getstatic"); - break; - case Opcodes.H_PUTFIELD: - sb.append("putfield"); - break; - case Opcodes.H_PUTSTATIC: - sb.append("putstatic"); - break; - case Opcodes.H_INVOKEINTERFACE: - sb.append("interface"); - break; - case Opcodes.H_INVOKESPECIAL: - sb.append("special"); - break; - case Opcodes.H_INVOKESTATIC: - sb.append("static"); - break; - case Opcodes.H_INVOKEVIRTUAL: - sb.append("virtual"); - break; - case Opcodes.H_NEWINVOKESPECIAL: - sb.append("new_special"); - break; - default: - assert false; - break; - } - sb.append(" '"); - sb.append(h.getName()); - sb.append("'"); - } - - private static void appendAccess(final StringBuilder sb, final int access) { - if ((access & Opcodes.ACC_PUBLIC) != 0) { - sb.append("public "); - } - if ((access & Opcodes.ACC_PRIVATE) != 0) { - sb.append("private "); - } - if ((access & Opcodes.ACC_PROTECTED) != 0) { - sb.append("protected "); - } - if ((access & Opcodes.ACC_FINAL) != 0) { - sb.append("final "); - } - if ((access & Opcodes.ACC_STATIC) != 0) { - sb.append("static "); - } - if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { - sb.append("synchronized "); - } - if ((access & Opcodes.ACC_VOLATILE) != 0) { - sb.append("volatile "); - } - if ((access & Opcodes.ACC_TRANSIENT) != 0) { - sb.append("transient "); - } - if ((access & Opcodes.ACC_ABSTRACT) != 0) { - sb.append("abstract "); - } - if ((access & Opcodes.ACC_STRICT) != 0) { - sb.append("strictfp "); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - sb.append("synthetic "); - } - if ((access & Opcodes.ACC_MANDATED) != 0) { - sb.append("mandated "); - } - if ((access & Opcodes.ACC_ENUM) != 0) { - sb.append("enum "); - } - } - - private void appendFrameTypes(final StringBuilder sb, final int n, final Object[] o) { - for (int i = 0; i < n; ++i) { - if (i > 0) { - sb.append(' '); - } - if (o[i] instanceof String) { - final String desc = (String) o[i]; - if (desc.startsWith("[")) { - appendDescriptor(sb, FIELD_DESCRIPTOR, desc); - } else { - appendDescriptor(sb, INTERNAL_NAME, desc); - } - } else if (o[i] instanceof Integer) { - switch (((Integer)o[i]).intValue()) { - case 0: - appendDescriptor(sb, FIELD_DESCRIPTOR, "T"); - break; - case 1: - appendDescriptor(sb, FIELD_DESCRIPTOR, "I"); - break; - case 2: - appendDescriptor(sb, FIELD_DESCRIPTOR, "F"); - break; - case 3: - appendDescriptor(sb, FIELD_DESCRIPTOR, "D"); - break; - case 4: - appendDescriptor(sb, FIELD_DESCRIPTOR, "J"); - break; - case 5: - appendDescriptor(sb, FIELD_DESCRIPTOR, "N"); - break; - case 6: - appendDescriptor(sb, FIELD_DESCRIPTOR, "U"); - break; - default: - assert false; - break; - } - } else { - appendLabel(sb, (Label) o[i]); - } - } - } - - private static void appendShortDescriptor(final StringBuilder sb, final String desc) { - //final StringBuilder buf = new StringBuilder(); - if (desc.charAt(0) == '(') { - for (int i = 0; i < desc.length(); i++) { - if (desc.charAt(i) == 'L') { - int slash = i; - while (desc.charAt(i) != ';') { - i++; - if (desc.charAt(i) == '/') { - slash = i; - } - } - sb.append(desc.substring(slash + 1, i)).append(';'); - } else { - sb.append(desc.charAt(i)); - } - } - } else { - final int lastSlash = desc.lastIndexOf('/'); - final int lastBracket = desc.lastIndexOf('['); - if(lastBracket != -1) { - sb.append(desc, 0, lastBracket + 1); - } - sb.append(lastSlash == -1 ? desc : desc.substring(lastSlash + 1)); - } - } - - private static void appendStr(final StringBuilder sb, final String s) { - sb.append('\"'); - for (int i = 0; i < s.length(); ++i) { - final char c = s.charAt(i); - if (c == '\n') { - sb.append("\\n"); - } else if (c == '\r') { - sb.append("\\r"); - } else if (c == '\\') { - sb.append("\\\\"); - } else if (c == '"') { - sb.append("\\\""); - } else if (c < 0x20 || c > 0x7f) { - sb.append("\\u"); - if (c < 0x10) { - sb.append("000"); - } else if (c < 0x100) { - sb.append("00"); - } else if (c < 0x1000) { - sb.append('0'); - } - sb.append(Integer.toString(c, 16)); - } else { - sb.append(c); - } - } - sb.append('\"'); - } - - private static class Graph { - private final LinkedHashSet<String> nodes; - private final Map<String, StringBuilder> contents; - private final Map<String, Set<String>> edges; - private final Set<String> hasPreds; - private final Set<String> noFallThru; - private final Map<String, String> catches; - private final Map<String, Set<String>> exceptionMap; //maps catch nodes to all their trys that can reach them - private final String name; - - private static final String LEFT_ALIGN = "\\l"; - private static final String COLOR_CATCH = "\"#ee9999\""; - private static final String COLOR_ORPHAN = "\"#9999bb\""; - private static final String COLOR_DEFAULT = "\"#99bb99\""; - private static final String COLOR_LOCALVARS = "\"#999999\""; - - Graph(final String name) { - this.name = name; - this.nodes = new LinkedHashSet<>(); - this.contents = new HashMap<>(); - this.edges = new HashMap<>(); - this.hasPreds = new HashSet<>(); - this.catches = new HashMap<>(); - this.noFallThru = new HashSet<>(); - this.exceptionMap = new HashMap<>(); - } - - void addEdge(final String from, final String to) { - Set<String> edgeSet = edges.get(from); - if (edgeSet == null) { - edgeSet = new LinkedHashSet<>(); - edges.put(from, edgeSet); - } - edgeSet.add(to); - hasPreds.add(to); - } - - void addTryCatch(final String tryNode, final String catchNode) { - Set<String> tryNodes = exceptionMap.get(catchNode); - if (tryNodes == null) { - tryNodes = new HashSet<>(); - exceptionMap.put(catchNode, tryNodes); - } - if (!tryNodes.contains(tryNode)) { - addEdge(tryNode, catchNode); - } - tryNodes.add(tryNode); - } - - void addNode(final String node) { - assert !nodes.contains(node); - nodes.add(node); - } - - void setNoFallThru(final String node) { - noFallThru.add(node); - } - - boolean isNoFallThru(final String node) { - return noFallThru.contains(node); - } - - void setIsCatch(final String node, final String exception) { - catches.put(node, exception); - } - - String getName() { - return name; - } - - void addText(final String node, final String text) { - StringBuilder sb = contents.get(node); - if (sb == null) { - sb = new StringBuilder(); - } - - for (int i = 0; i < text.length(); i++) { - switch (text.charAt(i)) { - case '\n': - sb.append(LEFT_ALIGN); - break; - case '"': - sb.append("'"); - break; - default: - sb.append(text.charAt(i)); - break; - } - } - - contents.put(node, sb); - } - - private static String dottyFriendly(final String name) { - return name.replace(':', '_'); - } - - @Override - public String toString() { - - final StringBuilder sb = new StringBuilder(); - sb.append("digraph " + dottyFriendly(name) + " {"); - sb.append("\n"); - sb.append("\tgraph [fontname=courier]\n"); - sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n"); - sb.append("\tedge [fontname=courier]\n\n"); - - for (final String node : nodes) { - sb.append("\t"); - sb.append(node); - sb.append(" ["); - sb.append("id="); - sb.append(node); - sb.append(", label=\""); - String c = contents.get(node).toString(); - if (c.startsWith(LEFT_ALIGN)) { - c = c.substring(LEFT_ALIGN.length()); - } - final String ex = catches.get(node); - if (ex != null) { - sb.append("*** CATCH: ").append(ex).append(" ***\\l"); - } - sb.append(c); - sb.append("\"]\n"); - } - - for (final String from : edges.keySet()) { - for (final String to : edges.get(from)) { - sb.append("\t"); - sb.append(from); - sb.append(" -> "); - sb.append(to); - sb.append("[label=\""); - sb.append(to); - sb.append("\""); - if (catches.get(to) != null) { - sb.append(", color=red, style=dashed"); - } - sb.append(']'); - sb.append(";\n"); - } - } - - sb.append("\n"); - for (final String node : nodes) { - sb.append("\t"); - sb.append(node); - sb.append(" [shape=box"); - if (catches.get(node) != null) { - sb.append(", color=" + COLOR_CATCH); - } else if ("vars".equals(node)) { - sb.append(", shape=hexagon, color=" + COLOR_LOCALVARS); - } else if (!hasPreds.contains(node)) { - sb.append(", color=" + COLOR_ORPHAN); - } - sb.append("]\n"); - } - - sb.append("}\n"); - return sb.toString(); - } - } - - static class NashornLabel extends Label { - final Label label; - final int bci; - final int opcode; - - NashornLabel(final Label label, final int bci) { - this.label = label; - this.bci = bci; - this.opcode = -1; - } - - //not an ASM label - NashornLabel(final int opcode, final int bci) { - this.opcode = opcode; - this.bci = bci; - this.label = null; - } - - Label getLabel() { - return label; - } - - @Override - public int getOffset() { - return bci; - } - - @Override - public String toString() { - return "label " + bci; - } - } - - @Override - public Printer visitAnnotationDefault() { - throw new AssertionError(); - } - - @Override - public Printer visitClassAnnotation(final String arg0, final boolean arg1) { - return this; - } - - @Override - public void visitClassAttribute(final Attribute arg0) { - throw new AssertionError(); - } - - @Override - public Printer visitFieldAnnotation(final String arg0, final boolean arg1) { - throw new AssertionError(); - } - - @Override - public void visitFieldAttribute(final Attribute arg0) { - throw new AssertionError(); - } - - @Override - public Printer visitMethodAnnotation(final String arg0, final boolean arg1) { - return this; - } - - @Override - public void visitMethodAttribute(final Attribute arg0) { - throw new AssertionError(); - } - - @Override - public Printer visitParameterAnnotation(final int arg0, final String arg1, final boolean arg2) { - throw new AssertionError(); - } - - @Override - public void visit(final String arg0, final Object arg1) { - throw new AssertionError(); - } - - @Override - public Printer visitAnnotation(final String arg0, final String arg1) { - throw new AssertionError(); - } - - @Override - public void visitAnnotationEnd() { - //empty - } - - @Override - public Printer visitArray(final String arg0) { - throw new AssertionError(); - } - - @Override - public void visitEnum(final String arg0, final String arg1, final String arg2) { - throw new AssertionError(); - } - - @Override - public void visitInnerClass(final String arg0, final String arg1, final String arg2, final int arg3) { - throw new AssertionError(); - } -} |