test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/Printer.java
changeset 50243 4fac3c99487d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/Printer.java	Wed May 23 17:09:49 2018 -0700
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2013, 2018, 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.
+ *
+ * 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 vm.runtime.defmeth.shared;
+
+import java.util.List;
+import java.util.ArrayList;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+import vm.runtime.defmeth.shared.data.*;
+import vm.runtime.defmeth.shared.data.method.*;
+import vm.runtime.defmeth.shared.data.method.body.*;
+import vm.runtime.defmeth.shared.data.method.param.*;
+import vm.runtime.defmeth.shared.data.method.result.*;
+
+import static java.lang.String.*;
+import nsk.share.Pair;
+
+
+/**
+ * Construct text representation of a class.
+ * Used to print generated class hierarchies.
+ */
+public class Printer implements Visitor {
+
+    private StringBuilder sb = new StringBuilder();
+    private Tester t;
+
+    private String output() {
+        return sb.toString();
+    }
+
+    static private String printAcc(int acc) {
+        List<String> flags = new ArrayList<>();
+
+        if ((acc & ACC_STATIC) != 0) {
+            flags.add("static");
+        }
+
+        if ((acc & ACC_PUBLIC) != 0) {
+            flags.add("public");
+        }
+
+        if ((acc & ACC_PRIVATE) != 0) {
+            flags.add("private");
+        }
+
+        if ((acc & ACC_PROTECTED) != 0) {
+            flags.add("protected");
+        }
+
+        if ((acc & ACC_PUBLIC) == 0 &&
+                (acc & ACC_PRIVATE) == 0 &&
+                (acc & ACC_PROTECTED) == 0) {
+            flags.add("package");
+        }
+
+        if ((acc & ACC_STRICT) != 0) {
+            flags.add("strictfp");
+        }
+
+        if ((acc & ACC_SYNCHRONIZED) != 0) {
+            flags.add("synchronized");
+        }
+
+        return Util.intersperse(" ", flags.toArray(new String[0]));
+    }
+    static public String print(Clazz clz) {
+        Printer p = new Printer();
+        clz.visit(p);
+        return p.output();
+    }
+
+    static public String print(Method m) {
+        Printer p = new Printer();
+        m.visit(p);
+        return p.output();
+    }
+
+    @Override
+    public void visitClass(Clazz clz) {
+        throw new IllegalStateException("More specific method should be called");
+    }
+
+    @Override
+    public void visitMethod(Method m) {
+        sb.append(String.format(
+                "%s%s",
+                m.name(), m.desc()));
+
+        if (m.sig() != null) {
+            sb.append("/* <").append(m.sig()).append("> */");
+        }
+    }
+
+    @Override
+    public void visitConcreteClass(ConcreteClass clz) {
+        sb.append("class ").append(clz.name()).append(" ");
+
+        if (!clz.parent().name().equals("java.lang.Object")) {
+            sb.append("extends ").append(clz.parent().name()).append(" ");
+        }
+
+        if (clz.interfaces().length > 0) {
+            sb.append("implements ");
+            sb.append(Util.intersperse(", ", Util.asStrings(clz.interfaces())));
+            sb.append(" ");
+        }
+
+        Method[] methods = clz.methods();
+
+        sb.append("{");
+        if (methods.length > 0) {
+            for (Method m : methods) {
+                sb.append("\n    ");
+                m.visit(this);
+            }
+            sb.append("\n");
+        }
+        sb.append("}");
+    }
+
+    @Override
+    public void visitInterface(Interface intf) {
+        sb.append("interface ").append(intf.name())
+                .append(" ");
+
+        if (intf.parents().length > 0) {
+            sb.append("extends ");
+            sb.append(Util.intersperse(", ", Util.asStrings(intf.parents())));
+            sb.append(" ");
+        }
+
+        Method[] methods = intf.methods();
+
+        sb.append("{");
+        if (methods.length > 0) {
+            for (Method m : methods) {
+                sb.append("\n    ");
+                m.visit(this);
+            }
+            sb.append("\n");
+        }
+        sb.append("}");
+    }
+    @Override
+
+    /* ====================================================================== */
+
+    public void visitTester(Tester t) {
+        this.t = t;
+
+        //sb.append(t.name()).append(": ");
+        sb.append("TEST: ");
+
+        //t.getCall().visit(this);
+        CallMethod call = t.getCall();
+
+        // call.receiverClass() is null when a .staticCallSite() invoke is
+        // used. There is a staticClass but no receiverClass.
+        sb.append(format("%s o = new %s(); o.%s%s",
+                call.staticClass().name(),
+                (call.receiverClass() == null ? "" : call.receiverClass().name()),
+                call.methodName(),
+                call.methodDesc()));
+
+        sb.append(" ");
+
+        t.getResult().visit(this);
+
+        this.t = null;
+    }
+
+    /* ====================================================================== */
+
+    @Override
+    public void visitAbstractMethod(AbstractMethod m) {
+        Pair<String[],String> desc = Util.parseDesc(m.desc());
+
+        sb.append(format(
+                "abstract %s %s %s(%s);",
+                printAcc(m.acc()),
+                Util.decodeClassName(desc.second),
+                m.name(),
+                Util.intersperse(", ", desc.first)));
+
+        if (m.sig() != null) {
+            sb.append("<").append(m.sig()).append(">");
+        }
+    }
+
+    @Override
+    public void visitConcreteMethod(ConcreteMethod m) {
+        Pair<String[],String> desc = Util.parseDesc(m.desc());
+
+        sb.append(format(
+                "%s %s %s(%s)",
+                printAcc(m.acc()),
+                Util.decodeClassName(desc.second),
+                m.name(),
+                Util.intersperse(", ", desc.first)));
+
+        if (m.sig() != null) {
+            sb.append("<").append(m.sig()).append(">");
+        }
+
+        sb.append(" ");
+
+        sb.append(" { ");
+        m.body().visit(this);
+        sb.append(" }");
+    }
+
+    @Override
+    public void visitDefaultMethod(DefaultMethod m) {
+        Pair<String[],String> desc = Util.parseDesc(m.desc());
+
+        sb.append(format(
+                "default %s %s %s(%s)",
+                printAcc(m.acc()),
+                Util.decodeClassName(desc.second),
+                m.name(),
+                Util.intersperse(", ", desc.first)));
+
+        if (m.sig() != null) {
+            sb.append("<").append(m.sig()).append(">");
+        }
+
+        sb.append(" { ");
+        m.body().visit(this);
+        sb.append(" }");
+    }
+
+    /* ====================================================================== */
+
+    @Override
+    public void visitThrowExBody(ThrowExBody body) {
+        sb.append(String.format(
+                "throw new %s();", body.getExc().name()));
+    }
+
+    @Override
+    public void visitReturnIntBody(ReturnIntBody body) {
+        sb.append(String.format(
+                "return %d;", body.getValue()));
+    }
+
+    @Override
+    public void visitReturnNullBody(ReturnNullBody body) {
+        sb.append("return null;");
+    }
+
+    @Override
+    public void visitEmptyBody(EmptyBody aThis) {
+    }
+
+    /* ====================================================================== */
+
+    @Override
+    public void visitResultIgnore() {
+        sb.append("/* result ignored */");
+    }
+
+    @Override
+    public void visitResultInt(IntResult res) {
+        sb.append("== ").append(res.getExpected());
+    }
+
+    @Override
+    public void visitResultThrowExc(ThrowExResult res) {
+        sb.append(String.format(
+                "throws %s%s",
+                abbreviateExcName(res.getExc().name()),
+                res.getMessage() != null ? "(\"" + res.getMessage() + "\")"  : ""));
+    }
+
+    private String abbreviateExcName(String name) {
+        switch(name) {
+            case "java.lang.AbstractMethodError" : return "AME";
+            case "java.lang.NoSuchMethodError"   : return "NSME";
+            default: return name.replaceAll("java\\.lang\\.", "");
+        }
+    }
+    /* ====================================================================== */
+
+    @Override
+    public void visitParamInt(IntParam param) {
+        sb.append(param.value());
+    }
+
+    @Override
+    public void visitParamString(StringParam param) {
+        sb.append(param.value());
+    }
+
+    @Override
+    public void visitParamNull() {
+        sb.append("null");
+    }
+    @Override
+    public void visitParamLong(LongParam param) {
+        sb.append(param.value());
+    }
+
+    @Override
+    public void visitParamFloat(FloatParam param) {
+        sb.append(param.value());
+    }
+
+    @Override
+    public void visitParamDouble(DoubleParam param) {
+        sb.append(param.value());
+    }
+
+    @Override
+    public void visitParamNewInstance(NewInstanceParam param) {
+        sb.append(String.format(
+                "new %s()",
+                param.clazz().name()));
+    }
+
+    @Override
+    public void visitCallMethod(CallMethod call) {
+        String[] paramTypes = Util.parseDesc(call.methodDesc()).first;
+
+        if (paramTypes.length != call.params().length) {
+            throw new IllegalStateException();
+        }
+
+        //sb.append("{ ");
+        if (!call.popReturnValue()) {
+            sb.append("return ");
+        }
+
+        switch (call.invokeInsn()) {
+            case VIRTUAL: case INTERFACE:
+                sb.append(String.format(
+                        "((%s)%s).%s(",
+                        call.staticClass().name(),
+                        call.receiverClass() != null ? call.receiverClass().name() : "this",
+                        call.methodName()));
+                break;
+            case STATIC:
+                sb.append(String.format(
+                        "%s.%s(",
+                        call.staticClass().name(),
+                        call.methodName()));
+                break;
+            case SPECIAL:
+                sb.append(String.format(
+                        "%s.super.%s(",
+                        call.staticClass().name(),
+                        call.methodName()));
+                break;
+            default:
+                throw new IllegalStateException();
+        }
+
+        for (int i = 0; i<paramTypes.length; i++) {
+            sb.append(String.format(
+                    "(%s)", paramTypes[i]));
+
+            call.params()[i].visit(this);
+
+            if (i+1 < paramTypes.length) {
+                sb.append(", ");
+            }
+        }
+
+        //sb.append("); }");
+        sb.append(");");
+    }
+
+    @Override
+    public void visitReturnNewInstanceBody(ReturnNewInstanceBody body) {
+        sb.append(String.format(
+                        "return new %s();",
+                        body.getType().name()));
+    }
+}