--- /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()));
+ }
+}