--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java Fri Feb 14 17:28:07 2014 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java Sat Feb 15 16:37:19 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -26,30 +26,10 @@
package com.sun.tools.javac.jvm;
import java.io.IOException;
-import java.io.Writer;
+import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import java.util.Stack;
-import java.util.StringTokenizer;
-
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.NoType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.TypeVisitor;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.SimpleTypeVisitor8;
-import javax.lang.model.util.Types;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
@@ -57,18 +37,22 @@
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.model.JavacElements;
-import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
+import com.sun.tools.javac.util.Pair;
import static com.sun.tools.javac.main.Option.*;
+import static com.sun.tools.javac.code.Kinds.*;
/** This class provides operations to write native header files for classes.
*
@@ -83,8 +67,8 @@
/** Access to files. */
private final JavaFileManager fileManager;
- JavacElements elements;
- JavacTypes types;
+ Types types;
+ Symtab syms;
/** The log to use for verbose output.
*/
@@ -98,15 +82,9 @@
*/
private boolean checkAll;
- private Mangle mangler;
-
private Context context;
- private Symtab syms;
-
- private String lineSep;
-
- private final boolean isWindows =
+ private static final boolean isWindows =
System.getProperty("os.name").startsWith("Windows");
/** Get the ClassWriter instance for this context. */
@@ -129,44 +107,58 @@
checkAll = options.isSet("javah:full");
this.context = context; // for lazyInit()
- syms = Symtab.instance(context);
-
- lineSep = System.getProperty("line.separator");
}
private void lazyInit() {
- if (mangler == null) {
- elements = JavacElements.instance(context);
- types = JavacTypes.instance(context);
- mangler = new Mangle(elements, types);
- }
+ if (types == null)
+ types = Types.instance(context);
+ if (syms == null)
+ syms = Symtab.instance(context);
+
+ }
+
+ static boolean isSynthetic(Symbol s) {
+ return hasFlag(s, Flags.SYNTHETIC);
+ }
+ static boolean isStatic(Symbol s) {
+ return hasFlag(s, Flags.STATIC);
+ }
+ static boolean isFinal(Symbol s) {
+ return hasFlag(s, Flags.FINAL);
+ }
+ static boolean isNative(Symbol s) {
+ return hasFlag(s, Flags.NATIVE);
+ }
+ static private boolean hasFlag(Symbol m, int flag) {
+ return (m.flags() & flag) != 0;
}
public boolean needsHeader(ClassSymbol c) {
- if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
+ lazyInit();
+ if (c.isLocal() || isSynthetic(c))
return false;
-
- if (checkAll)
- return needsHeader(c.outermostClass(), true);
- else
- return needsHeader(c, false);
+ return (checkAll)
+ ? needsHeader(c.outermostClass(), true)
+ : needsHeader(c, false);
}
private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) {
- if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
+ if (c.isLocal() || isSynthetic(c))
return false;
for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
- if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
+ Symbol sym = i.sym;
+ if (sym.kind == MTH && isNative(sym))
return true;
- for (Attribute.Compound a: i.sym.getDeclarationAttributes()) {
+ for (Attribute.Compound a: sym.getDeclarationAttributes()) {
if (a.type.tsym == syms.nativeHeaderType.tsym)
return true;
}
}
if (checkNestedClasses) {
for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
- if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true))
+ Symbol sym = i.sym;
+ if ((sym.kind == TYP) && needsHeader(((ClassSymbol) sym), true))
return true;
}
}
@@ -176,14 +168,12 @@
/** Emit a class file for a given class.
* @param c The class from which a class file is generated.
*/
- public FileObject write(ClassSymbol c)
- throws IOException
- {
+ public FileObject write(ClassSymbol c) throws IOException {
String className = c.flatName().toString();
FileObject outFile
= fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
"", className.replaceAll("[.$]", "_") + ".h", null);
- Writer out = outFile.openWriter();
+ PrintWriter out = new PrintWriter(outFile.openWriter());
try {
write(out, c);
if (verbose)
@@ -201,201 +191,134 @@
return outFile; // may be null if write failed
}
- public void write(Writer out, ClassSymbol sym)
- throws IOException {
+ public void write(PrintWriter out, ClassSymbol sym) throws IOException {
lazyInit();
try {
- String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS);
- println(out, fileTop());
- println(out, includes());
- println(out, guardBegin(cname));
- println(out, cppGuardBegin());
+ String cname = encode(sym.fullname, EncoderType.CLASS);
+ fileTop(out);
+ includes(out);
+ guardBegin(out, cname);
+ cppGuardBegin(out);
writeStatics(out, sym);
writeMethods(out, sym, cname);
- println(out, cppGuardEnd());
- println(out, guardEnd(cname));
+ cppGuardEnd(out);
+ guardEnd(out);
} catch (TypeSignature.SignatureException e) {
throw new IOException(e);
}
}
-
- protected void writeStatics(Writer out, ClassSymbol sym) throws IOException {
- List<VariableElement> classfields = getAllFields(sym);
-
- for (VariableElement v: classfields) {
- if (!v.getModifiers().contains(Modifier.STATIC))
- continue;
- String s = null;
- s = defineForStatic(sym, v);
- if (s != null) {
- println(out, s);
+ protected void writeStatics(PrintWriter out, ClassSymbol sym) throws IOException {
+ List<ClassSymbol> clist = new ArrayList<>();
+ for (ClassSymbol cd = sym; cd != null;
+ cd = (ClassSymbol) cd.getSuperclass().tsym) {
+ clist.add(cd);
+ }
+ /*
+ * list needs to be super-class, base-class1, base-class2 and so on,
+ * so we reverse class hierarchy
+ */
+ Collections.reverse(clist);
+ for (ClassSymbol cd : clist) {
+ for (Symbol i : cd.getEnclosedElements()) {
+ // consider only final, static and fields with ConstantExpressions
+ if (isFinal(i) && i.isStatic() && i.kind == VAR) {
+ VarSymbol v = (VarSymbol) i;
+ if (v.getConstantValue() != null) {
+ Pair<ClassSymbol, VarSymbol> p = new Pair<>(sym, v);
+ printStaticDefines(out, p);
+ }
+ }
}
}
}
-
- /**
- * Including super class fields.
- */
- List<VariableElement> getAllFields(TypeElement subclazz) {
- List<VariableElement> fields = new ArrayList<>();
- TypeElement cd = null;
- Stack<TypeElement> s = new Stack<>();
-
- cd = subclazz;
- while (true) {
- s.push(cd);
- TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
- if (c == null)
+ static void printStaticDefines(PrintWriter out, Pair<ClassSymbol, VarSymbol> p) {
+ ClassSymbol cls = p.fst;
+ VarSymbol f = p.snd;
+ Object value = f.getConstantValue();
+ String valueStr = null;
+ switch (f.asType().getKind()) {
+ case BOOLEAN:
+ valueStr = (((Boolean) value) ? "1L" : "0L");
+ break;
+ case BYTE: case SHORT: case INT:
+ valueStr = value.toString() + "L";
+ break;
+ case LONG:
+ // Visual C++ supports the i64 suffix, not LL.
+ valueStr = value.toString() + ((isWindows) ? "i64" : "LL");
+ break;
+ case CHAR:
+ Character ch = (Character) value;
+ valueStr = String.valueOf(((int) ch) & 0xffff) + "L";
break;
- cd = c;
+ case FLOAT:
+ // bug compatible
+ float fv = ((Float) value).floatValue();
+ valueStr = (Float.isInfinite(fv))
+ ? ((fv < 0) ? "-" : "") + "Inff"
+ : value.toString() + "f";
+ break;
+ case DOUBLE:
+ // bug compatible
+ double d = ((Double) value).doubleValue();
+ valueStr = (Double.isInfinite(d))
+ ? ((d < 0) ? "-" : "") + "InfD"
+ : value.toString();
+ break;
+ default:
+ valueStr = null;
}
-
- while (!s.empty()) {
- cd = s.pop();
- fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
+ if (valueStr != null) {
+ out.print("#undef ");
+ String cname = encode(cls.getQualifiedName(), EncoderType.CLASS);
+ String fname = encode(f.getSimpleName(), EncoderType.FIELDSTUB);
+ out.println(cname + "_" + fname);
+ out.print("#define " + cname + "_");
+ out.println(fname + " " + valueStr);
}
-
- return fields;
}
-
- protected String defineForStatic(TypeElement c, VariableElement f) {
- CharSequence cnamedoc = c.getQualifiedName();
- CharSequence fnamedoc = f.getSimpleName();
-
- String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
- String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
-
- Assert.check(f.getModifiers().contains(Modifier.STATIC));
-
- if (f.getModifiers().contains(Modifier.FINAL)) {
- Object value = null;
-
- value = f.getConstantValue();
-
- if (value != null) { /* so it is a ConstantExpression */
- String constString = null;
- if ((value instanceof Integer)
- || (value instanceof Byte)
- || (value instanceof Short)) {
- /* covers byte, short, int */
- constString = value.toString() + "L";
- } else if (value instanceof Boolean) {
- constString = ((Boolean) value) ? "1L" : "0L";
- } else if (value instanceof Character) {
- Character ch = (Character) value;
- constString = String.valueOf(((int) ch) & 0xffff) + "L";
- } else if (value instanceof Long) {
- // Visual C++ supports the i64 suffix, not LL.
- if (isWindows)
- constString = value.toString() + "i64";
- else
- constString = value.toString() + "LL";
- } else if (value instanceof Float) {
- /* bug for bug */
- float fv = ((Float)value).floatValue();
- if (Float.isInfinite(fv))
- constString = ((fv < 0) ? "-" : "") + "Inff";
- else
- constString = value.toString() + "f";
- } else if (value instanceof Double) {
- /* bug for bug */
- double d = ((Double)value).doubleValue();
- if (Double.isInfinite(d))
- constString = ((d < 0) ? "-" : "") + "InfD";
- else
- constString = value.toString();
+ protected void writeMethods(PrintWriter out, ClassSymbol sym, String cname)
+ throws IOException, TypeSignature.SignatureException {
+ List<Symbol> classmethods = sym.getEnclosedElements();
+ for (Symbol md : classmethods) {
+ if (isNative(md)) {
+ TypeSignature newtypesig = new TypeSignature(types);
+ CharSequence methodName = md.getSimpleName();
+ boolean isOverloaded = false;
+ for (Symbol md2 : classmethods) {
+ if ((md2 != md)
+ && (methodName.equals(md2.getSimpleName()))
+ && isNative(md2)) {
+ isOverloaded = true;
+ }
}
-
- if (constString != null) {
- StringBuilder s = new StringBuilder("#undef ");
- s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
- s.append("#define "); s.append(cname); s.append("_");
- s.append(fname); s.append(" "); s.append(constString);
- return s.toString();
+ out.println("/*");
+ out.println(" * Class: " + cname);
+ out.println(" * Method: " + encode(methodName, EncoderType.FIELDSTUB));
+ out.println(" * Signature: " + newtypesig.getSignature(md.type));
+ out.println(" */");
+ out.println("JNIEXPORT " + jniType(types.erasure(md.type.getReturnType()))
+ + " JNICALL " + encodeMethod(md, sym, isOverloaded));
+ out.print(" (JNIEnv *, ");
+ out.print((md.isStatic())
+ ? "jclass"
+ : "jobject");
+ for (Type arg : types.erasure(md.type.getParameterTypes())) {
+ out.print(", ");
+ out.print(jniType(arg));
}
-
- }
- }
-
- return null;
- }
-
-
- protected void writeMethods(Writer out, ClassSymbol sym, String cname)
- throws IOException, TypeSignature.SignatureException {
- List<ExecutableElement> classmethods = ElementFilter.methodsIn(sym.getEnclosedElements());
- for (ExecutableElement md: classmethods) {
- if(md.getModifiers().contains(Modifier.NATIVE)){
- TypeMirror mtr = types.erasure(md.getReturnType());
- String sig = signature(md);
- TypeSignature newtypesig = new TypeSignature(elements);
- CharSequence methodName = md.getSimpleName();
- boolean longName = false;
- for (ExecutableElement md2: classmethods) {
- if ((md2 != md)
- && (methodName.equals(md2.getSimpleName()))
- && (md2.getModifiers().contains(Modifier.NATIVE)))
- longName = true;
-
- }
- println(out, "/*");
- println(out, " * Class: " + cname);
- println(out, " * Method: " +
- mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
- println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr));
- println(out, " */");
- println(out, "JNIEXPORT " + jniType(mtr) +
- " JNICALL " +
- mangler.mangleMethod(md, sym,
- (longName) ?
- Mangle.Type.METHOD_JNI_LONG :
- Mangle.Type.METHOD_JNI_SHORT));
- print(out, " (JNIEnv *, ");
- List<? extends VariableElement> paramargs = md.getParameters();
- List<TypeMirror> args = new ArrayList<>();
- for (VariableElement p: paramargs) {
- args.add(types.erasure(p.asType()));
- }
- if (md.getModifiers().contains(Modifier.STATIC))
- print(out, "jclass");
- else
- print(out, "jobject");
-
- for (TypeMirror arg: args) {
- print(out, ", ");
- print(out, jniType(arg));
- }
- println(out, ");"
- + lineSep);
+ out.println(");");
+ out.println();
}
}
}
-
- // c.f. MethodDoc.signature
- String signature(ExecutableElement e) {
- StringBuilder sb = new StringBuilder("(");
- String sep = "";
- for (VariableElement p: e.getParameters()) {
- sb.append(sep);
- sb.append(types.erasure(p.asType()).toString());
- sep = ",";
- }
- sb.append(")");
- return sb.toString();
- }
-
- protected final String jniType(TypeMirror t) {
- TypeElement throwable = elements.getTypeElement("java.lang.Throwable");
- TypeElement jClass = elements.getTypeElement("java.lang.Class");
- TypeElement jString = elements.getTypeElement("java.lang.String");
- Element tclassDoc = types.asElement(t);
-
-
+ @SuppressWarnings("fallthrough")
+ protected final String jniType(Type t) {
switch (t.getKind()) {
case ARRAY: {
- TypeMirror ct = ((ArrayType) t).getComponentType();
+ Type ct = ((Type.ArrayType)t).getComponentType();
switch (ct.getKind()) {
case BOOLEAN: return "jbooleanArray";
case BYTE: return "jbyteArray";
@@ -420,16 +343,16 @@
case LONG: return "jlong";
case FLOAT: return "jfloat";
case DOUBLE: return "jdouble";
-
case DECLARED: {
- if (tclassDoc.equals(jString))
+ if (t.tsym.type == syms.stringType) {
return "jstring";
- else if (types.isAssignable(t, throwable.asType()))
+ } else if (types.isAssignable(t, syms.throwableType)) {
return "jthrowable";
- else if (types.isAssignable(t, jClass.asType()))
+ } else if (types.isAssignable(t, syms.classType)) {
return "jclass";
- else
+ } else {
return "jobject";
+ }
}
}
@@ -437,193 +360,145 @@
return null; /* dead code. */
}
- protected String fileTop() {
- return "/* DO NOT EDIT THIS FILE - it is machine generated */";
+ protected void fileTop(PrintWriter out) {
+ out.println("/* DO NOT EDIT THIS FILE - it is machine generated */");
}
- protected String includes() {
- return "#include <jni.h>";
+ protected void includes(PrintWriter out) {
+ out.println("#include <jni.h>");
}
/*
* Deal with the C pre-processor.
*/
- protected String cppGuardBegin() {
- return "#ifdef __cplusplus" + lineSep
- + "extern \"C\" {" + lineSep
- + "#endif";
+ protected void cppGuardBegin(PrintWriter out) {
+ out.println("#ifdef __cplusplus");
+ out.println("extern \"C\" {");
+ out.println("#endif");
}
- protected String cppGuardEnd() {
- return "#ifdef __cplusplus" + lineSep
- + "}" + lineSep
- + "#endif";
+ protected void cppGuardEnd(PrintWriter out) {
+ out.println("#ifdef __cplusplus");
+ out.println("}");
+ out.println("#endif");
+ }
+
+ protected void guardBegin(PrintWriter out, String cname) {
+ out.println("/* Header for class " + cname + " */");
+ out.println();
+ out.println("#ifndef _Included_" + cname);
+ out.println("#define _Included_" + cname);
}
- protected String guardBegin(String cname) {
- return "/* Header for class " + cname + " */" + lineSep
- + lineSep
- + "#ifndef _Included_" + cname + lineSep
- + "#define _Included_" + cname;
+ protected void guardEnd(PrintWriter out) {
+ out.println("#endif");
}
- protected String guardEnd(String cname) {
- return "#endif";
- }
-
- protected void print(Writer out, String text) throws IOException {
- out.write(text);
- }
-
- protected void println(Writer out, String text) throws IOException {
- out.write(text);
- out.write(lineSep);
+ String encodeMethod(Symbol msym, ClassSymbol clazz,
+ boolean isOverloaded) throws TypeSignature.SignatureException {
+ StringBuilder result = new StringBuilder(100);
+ result.append("Java_");
+ /* JNI */
+ result.append(encode(clazz.flatname.toString(), EncoderType.JNI));
+ result.append('_');
+ result.append(encode(msym.getSimpleName(), EncoderType.JNI));
+ if (isOverloaded) {
+ TypeSignature typeSig = new TypeSignature(types);
+ StringBuilder sig = typeSig.getParameterSignature(msym.type);
+ result.append("__").append(encode(sig, EncoderType.JNI));
+ }
+ return result.toString();
}
-
- private static class Mangle {
-
- public static class Type {
- public static final int CLASS = 1;
- public static final int FIELDSTUB = 2;
- public static final int FIELD = 3;
- public static final int JNI = 4;
- public static final int SIGNATURE = 5;
- public static final int METHOD_JDK_1 = 6;
- public static final int METHOD_JNI_SHORT = 7;
- public static final int METHOD_JNI_LONG = 8;
- }
-
- private Elements elems;
- private Types types;
-
- Mangle(Elements elems, Types types) {
- this.elems = elems;
- this.types = types;
- }
-
- public final String mangle(CharSequence name, int mtype) {
- StringBuilder result = new StringBuilder(100);
- int length = name.length();
-
- for (int i = 0; i < length; i++) {
- char ch = name.charAt(i);
- if (isalnum(ch)) {
- result.append(ch);
- } else if ((ch == '.') &&
- mtype == Mangle.Type.CLASS) {
- result.append('_');
- } else if (( ch == '$') &&
- mtype == Mangle.Type.CLASS) {
- result.append('_');
- result.append('_');
- } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
- result.append('_');
- } else if (ch == '_' && mtype == Mangle.Type.CLASS) {
- result.append('_');
- } else if (mtype == Mangle.Type.JNI) {
- String esc = null;
- if (ch == '_')
- esc = "_1";
- else if (ch == '.')
- esc = "_";
- else if (ch == ';')
- esc = "_2";
- else if (ch == '[')
- esc = "_3";
- if (esc != null) {
- result.append(esc);
- } else {
- result.append(mangleChar(ch));
- }
- } else if (mtype == Mangle.Type.SIGNATURE) {
- if (isprint(ch)) {
- result.append(ch);
- } else {
- result.append(mangleChar(ch));
- }
- } else {
- result.append(mangleChar(ch));
- }
- }
-
- return result.toString();
- }
+ static enum EncoderType {
+ CLASS,
+ FIELDSTUB,
+ FIELD,
+ JNI,
+ SIGNATURE
+ }
+ @SuppressWarnings("fallthrough")
+ static String encode(CharSequence name, EncoderType mtype) {
+ StringBuilder result = new StringBuilder(100);
+ int length = name.length();
- public String mangleMethod(ExecutableElement method, TypeElement clazz,
- int mtype) throws TypeSignature.SignatureException {
- StringBuilder result = new StringBuilder(100);
- result.append("Java_");
-
- if (mtype == Mangle.Type.METHOD_JDK_1) {
- result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
- result.append('_');
- result.append(mangle(method.getSimpleName(),
- Mangle.Type.FIELD));
- result.append("_stub");
- return result.toString();
+ for (int i = 0; i < length; i++) {
+ char ch = name.charAt(i);
+ if (isalnum(ch)) {
+ result.append(ch);
+ continue;
}
-
- /* JNI */
- result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
- result.append('_');
- result.append(mangle(method.getSimpleName(),
- Mangle.Type.JNI));
- if (mtype == Mangle.Type.METHOD_JNI_LONG) {
- result.append("__");
- String typesig = signature(method);
- TypeSignature newTypeSig = new TypeSignature(elems);
- String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType());
- sig = sig.substring(1);
- sig = sig.substring(0, sig.lastIndexOf(')'));
- sig = sig.replace('/', '.');
- result.append(mangle(sig, Mangle.Type.JNI));
+ switch (mtype) {
+ case CLASS:
+ switch (ch) {
+ case '.':
+ case '_':
+ result.append("_");
+ break;
+ case '$':
+ result.append("__");
+ break;
+ default:
+ result.append(encodeChar(ch));
+ }
+ break;
+ case JNI:
+ switch (ch) {
+ case '/':
+ case '.':
+ result.append("_");
+ break;
+ case '_':
+ result.append("_1");
+ break;
+ case ';':
+ result.append("_2");
+ break;
+ case '[':
+ result.append("_3");
+ break;
+ default:
+ result.append(encodeChar(ch));
+ }
+ break;
+ case SIGNATURE:
+ result.append(isprint(ch) ? ch : encodeChar(ch));
+ break;
+ case FIELDSTUB:
+ result.append(ch == '_' ? ch : encodeChar(ch));
+ break;
+ default:
+ result.append(encodeChar(ch));
}
-
- return result.toString();
}
- //where
- private String getInnerQualifiedName(TypeElement clazz) {
- return elems.getBinaryName(clazz).toString();
- }
+ return result.toString();
+ }
- public final String mangleChar(char ch) {
- String s = Integer.toHexString(ch);
- int nzeros = 5 - s.length();
- char[] result = new char[6];
- result[0] = '_';
- for (int i = 1; i <= nzeros; i++)
- result[i] = '0';
- for (int i = nzeros+1, j = 0; i < 6; i++, j++)
- result[i] = s.charAt(j);
- return new String(result);
+ static String encodeChar(char ch) {
+ String s = Integer.toHexString(ch);
+ int nzeros = 5 - s.length();
+ char[] result = new char[6];
+ result[0] = '_';
+ for (int i = 1; i <= nzeros; i++) {
+ result[i] = '0';
}
+ for (int i = nzeros + 1, j = 0; i < 6; i++, j++) {
+ result[i] = s.charAt(j);
+ }
+ return new String(result);
+ }
- // Warning: duplicated in Gen
- private String signature(ExecutableElement e) {
- StringBuilder sb = new StringBuilder();
- String sep = "(";
- for (VariableElement p: e.getParameters()) {
- sb.append(sep);
- sb.append(types.erasure(p.asType()).toString());
- sep = ",";
- }
- sb.append(")");
- return sb.toString();
- }
+ /* Warning: Intentional ASCII operation. */
+ private static boolean isalnum(char ch) {
+ return ch <= 0x7f && /* quick test */
+ ((ch >= 'A' && ch <= 'Z') ||
+ (ch >= 'a' && ch <= 'z') ||
+ (ch >= '0' && ch <= '9'));
+ }
- /* Warning: Intentional ASCII operation. */
- private static boolean isalnum(char ch) {
- return ch <= 0x7f && /* quick test */
- ((ch >= 'A' && ch <= 'Z') ||
- (ch >= 'a' && ch <= 'z') ||
- (ch >= '0' && ch <= '9'));
- }
-
- /* Warning: Intentional ASCII operation. */
- private static boolean isprint(char ch) {
- return ch >= 32 && ch <= 126;
- }
+ /* Warning: Intentional ASCII operation. */
+ private static boolean isprint(char ch) {
+ return ch >= 32 && ch <= 126;
}
private static class TypeSignature {
@@ -634,10 +509,10 @@
}
}
- Elements elems;
+ JavacElements elems;
+ Types types;
/* Signature Characters */
-
private static final String SIG_VOID = "V";
private static final String SIG_BOOLEAN = "Z";
private static final String SIG_BYTE = "B";
@@ -650,209 +525,162 @@
private static final String SIG_ARRAY = "[";
private static final String SIG_CLASS = "L";
-
-
- public TypeSignature(Elements elems){
- this.elems = elems;
- }
-
- /*
- * Returns the type signature of a field according to JVM specs
- */
- public String getTypeSignature(String javasignature) throws SignatureException {
- return getParamJVMSignature(javasignature);
+ public TypeSignature(Types types) {
+ this.types = types;
}
- /*
- * Returns the type signature of a method according to JVM specs
- */
- public String getTypeSignature(String javasignature, TypeMirror returnType)
+ StringBuilder getParameterSignature(Type mType)
throws SignatureException {
- String signature = null; //Java type signature.
- String typeSignature = null; //Internal type signature.
- List<String> params = new ArrayList<>(); //List of parameters.
- String paramsig = null; //Java parameter signature.
- String paramJVMSig = null; //Internal parameter signature.
- String returnSig = null; //Java return type signature.
- String returnJVMType = null; //Internal return type signature.
- int dimensions = 0; //Array dimension.
-
- int startIndex = -1;
- int endIndex = -1;
- StringTokenizer st = null;
- int i = 0;
-
- // Gets the actual java signature without parentheses.
- if (javasignature != null) {
- startIndex = javasignature.indexOf("(");
- endIndex = javasignature.indexOf(")");
+ StringBuilder result = new StringBuilder();
+ for (Type pType : mType.getParameterTypes()) {
+ result.append(getJvmSignature(pType));
}
-
- if (((startIndex != -1) && (endIndex != -1))
- &&(startIndex+1 < javasignature.length())
- &&(endIndex < javasignature.length())) {
- signature = javasignature.substring(startIndex+1, endIndex);
- }
+ return result;
+ }
- // Separates parameters.
- if (signature != null) {
- if (signature.contains(",")) {
- st = new StringTokenizer(signature, ",");
- if (st != null) {
- while (st.hasMoreTokens()) {
- params.add(st.nextToken());
- }
- }
- } else {
- params.add(signature);
- }
- }
-
- /* JVM type signature. */
- typeSignature = "(";
+ StringBuilder getReturnSignature(Type mType)
+ throws SignatureException {
+ return getJvmSignature(mType.getReturnType());
+ }
- // Gets indivisual internal parameter signature.
- while (params.isEmpty() != true) {
- paramsig = params.remove(i).trim();
- paramJVMSig = getParamJVMSignature(paramsig);
- if (paramJVMSig != null) {
- typeSignature += paramJVMSig;
- }
- }
-
- typeSignature += ")";
-
- // Get internal return type signature.
-
- returnJVMType = "";
- if (returnType != null) {
- dimensions = dimensions(returnType);
- }
-
- //Gets array dimension of return type.
- while (dimensions-- > 0) {
- returnJVMType += "[";
- }
- if (returnType != null) {
- returnSig = qualifiedTypeName(returnType);
- returnJVMType += getComponentType(returnSig);
- } else {
- System.out.println("Invalid return type.");
- }
-
- typeSignature += returnJVMType;
-
- return typeSignature;
+ StringBuilder getSignature(Type mType) throws SignatureException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(").append(getParameterSignature(mType)).append(")");
+ sb.append(getReturnSignature(mType));
+ return sb;
}
/*
- * Returns internal signature of a parameter.
+ * Returns jvm internal signature.
*/
- private String getParamJVMSignature(String paramsig) throws SignatureException {
- String paramJVMSig = "";
- String componentType ="";
+ static class JvmTypeVisitor extends JNIWriter.SimpleTypeVisitor<Type, StringBuilder> {
- if(paramsig != null){
+ @Override
+ public Type visitClassType(Type.ClassType t, StringBuilder s) {
+ setDeclaredType(t, s);
+ return null;
+ }
+
+ @Override
+ public Type visitArrayType(Type.ArrayType t, StringBuilder s) {
+ s.append("[");
+ return t.getComponentType().accept(this, s);
+ }
- if(paramsig.contains("[]")) {
- // Gets array dimension.
- int endindex = paramsig.indexOf("[]");
- componentType = paramsig.substring(0, endindex);
- String dimensionString = paramsig.substring(endindex);
- if(dimensionString != null){
- while(dimensionString.contains("[]")){
- paramJVMSig += "[";
- int beginindex = dimensionString.indexOf("]") + 1;
- if(beginindex < dimensionString.length()){
- dimensionString = dimensionString.substring(beginindex);
- }else
- dimensionString = "";
- }
- }
- } else componentType = paramsig;
-
- paramJVMSig += getComponentType(componentType);
+ @Override
+ public Type visitType(Type t, StringBuilder s) {
+ if (t.isPrimitiveOrVoid()) {
+ s.append(getJvmPrimitiveSignature(t));
+ return null;
+ }
+ return t.accept(this, s);
+ }
+ private void setDeclaredType(Type t, StringBuilder s) {
+ String classname = t.tsym.getQualifiedName().toString();
+ classname = classname.replace('.', '/');
+ s.append("L").append(classname).append(";");
}
- return paramJVMSig;
+ private String getJvmPrimitiveSignature(Type t) {
+ switch (t.getKind()) {
+ case VOID: return SIG_VOID;
+ case BOOLEAN: return SIG_BOOLEAN;
+ case BYTE: return SIG_BYTE;
+ case CHAR: return SIG_CHAR;
+ case SHORT: return SIG_SHORT;
+ case INT: return SIG_INT;
+ case LONG: return SIG_LONG;
+ case FLOAT: return SIG_FLOAT;
+ case DOUBLE: return SIG_DOUBLE;
+ default:
+ Assert.error("unknown type: should not happen");
+ }
+ return null;
+ }
}
- /*
- * Returns internal signature of a component.
- */
- private String getComponentType(String componentType) throws SignatureException {
-
- String JVMSig = "";
-
- if(componentType != null){
- switch (componentType) {
- case "void": JVMSig += SIG_VOID; break;
- case "boolean": JVMSig += SIG_BOOLEAN; break;
- case "byte": JVMSig += SIG_BYTE; break;
- case "char": JVMSig += SIG_CHAR; break;
- case "short": JVMSig += SIG_SHORT; break;
- case "int": JVMSig += SIG_INT; break;
- case "long": JVMSig += SIG_LONG; break;
- case "float": JVMSig += SIG_FLOAT; break;
- case "double": JVMSig += SIG_DOUBLE; break;
- default:
- if (!componentType.equals("")) {
- TypeElement classNameDoc = elems.getTypeElement(componentType);
-
- if (classNameDoc == null) {
- throw new SignatureException(componentType);
- }
- else {
- String classname = classNameDoc.getQualifiedName().toString();
- String newclassname = classname.replace('.', '/');
- JVMSig += "L";
- JVMSig += newclassname;
- JVMSig += ";";
- }
- }
- break;
- }
- }
- return JVMSig;
- }
-
- int dimensions(TypeMirror t) {
- if (t.getKind() != TypeKind.ARRAY)
- return 0;
- return 1 + dimensions(((ArrayType) t).getComponentType());
- }
-
-
- String qualifiedTypeName(TypeMirror type) {
- TypeVisitor<Name, Void> v = new SimpleTypeVisitor8<Name, Void>() {
- @Override
- public Name visitArray(ArrayType t, Void p) {
- return t.getComponentType().accept(this, p);
- }
-
- @Override
- public Name visitDeclared(DeclaredType t, Void p) {
- return ((TypeElement) t.asElement()).getQualifiedName();
- }
-
- @Override
- public Name visitPrimitive(PrimitiveType t, Void p) {
- return elems.getName(t.toString());
- }
-
- @Override
- public Name visitNoType(NoType t, Void p) {
- if (t.getKind() == TypeKind.VOID)
- return elems.getName("void");
- return defaultAction(t, p);
- }
-
- @Override
- public Name visitTypeVariable(TypeVariable t, Void p) {
- return t.getUpperBound().accept(this, p);
- }
- };
- return v.visit(type).toString();
+ StringBuilder getJvmSignature(Type type) {
+ Type t = types.erasure(type);
+ StringBuilder sig = new StringBuilder();
+ JvmTypeVisitor jv = new JvmTypeVisitor();
+ jv.visitType(t, sig);
+ return sig;
}
}
+ static class SimpleTypeVisitor<R, P> implements Type.Visitor<R, P> {
+
+ protected final R DEFAULT_VALUE;
+
+ protected SimpleTypeVisitor() {
+ DEFAULT_VALUE = null;
+ }
+
+ protected SimpleTypeVisitor(R defaultValue) {
+ DEFAULT_VALUE = defaultValue;
+ }
+
+ protected R defaultAction(Type t, P p) {
+ return DEFAULT_VALUE;
+ }
+
+ @Override
+ public R visitClassType(Type.ClassType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitWildcardType(Type.WildcardType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitArrayType(Type.ArrayType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitMethodType(Type.MethodType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitPackageType(Type.PackageType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitTypeVar(Type.TypeVar t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitCapturedType(Type.CapturedType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitForAll(Type.ForAll t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitUndetVar(Type.UndetVar t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitErrorType(Type.ErrorType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitAnnotatedType(Type.AnnotatedType t, P p) {
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public R visitType(Type t, P p) {
+ return defaultAction(t, p);
+ }
+ }
}