--- old/src/jdk.compiler/share/classes/com/sun/tools/javah/LLNI.java 2017-11-09 15:06:37.873817535 -0800 +++ /dev/null 2017-01-21 22:54:52.877512947 -0800 @@ -1,685 +0,0 @@ -/* - * Copyright (c) 2002, 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 - * 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 com.sun.tools.javah; - -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -import java.util.Set; -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.PrimitiveType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVisitor; -import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.SimpleTypeVisitor9; - -import com.sun.tools.javac.util.DefinedBy; -import com.sun.tools.javac.util.DefinedBy.Api; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

- * - * @author Sucheta Dambalkar(Revised) - */ -public class LLNI extends Gen { - - protected final char innerDelim = '$'; /* For inner classes */ - protected Set doneHandleTypes; - List fields; - List methods; - private boolean doubleAlign; - private int padFieldNum = 0; - - LLNI(boolean doubleAlign, Util util) { - super(util); - this.doubleAlign = doubleAlign; - } - - protected String getIncludes() { - return ""; - } - - protected void write(OutputStream o, TypeElement clazz) throws Util.Exit { - try { - String cname = mangleClassName(clazz.getQualifiedName().toString()); - PrintWriter pw = wrapWriter(o); - fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); - methods = ElementFilter.methodsIn(clazz.getEnclosedElements()); - generateDeclsForClass(pw, clazz, cname); - // FIXME check if errors occurred on the PrintWriter and throw exception if so - } catch (TypeSignature.SignatureException e) { - util.error("llni.sigerror", e.getMessage()); - } - } - - protected void generateDeclsForClass(PrintWriter pw, - TypeElement clazz, String cname) - throws TypeSignature.SignatureException, Util.Exit { - doneHandleTypes = new HashSet<>(); - /* The following handle types are predefined in "typedefs.h". Suppress - inclusion in the output by generating them "into the blue" here. */ - genHandleType(null, "java.lang.Class"); - genHandleType(null, "java.lang.ClassLoader"); - genHandleType(null, "java.lang.Object"); - genHandleType(null, "java.lang.String"); - genHandleType(null, "java.lang.Thread"); - genHandleType(null, "java.lang.ThreadGroup"); - genHandleType(null, "java.lang.Throwable"); - - pw.println("/* LLNI Header for class " + clazz.getQualifiedName() + " */" + lineSep); - pw.println("#ifndef _Included_" + cname); - pw.println("#define _Included_" + cname); - pw.println("#include \"typedefs.h\""); - pw.println("#include \"llni.h\""); - pw.println("#include \"jni.h\"" + lineSep); - - forwardDecls(pw, clazz); - structSectionForClass(pw, clazz, cname); - methodSectionForClass(pw, clazz, cname); - pw.println("#endif"); - } - - protected void genHandleType(PrintWriter pw, String clazzname) { - String cname = mangleClassName(clazzname); - if (!doneHandleTypes.contains(cname)) { - doneHandleTypes.add(cname); - if (pw != null) { - pw.println("#ifndef DEFINED_" + cname); - pw.println(" #define DEFINED_" + cname); - pw.println(" GEN_HANDLE_TYPES(" + cname + ");"); - pw.println("#endif" + lineSep); - } - } - } - - protected String mangleClassName(String s) { - return s.replace('.', '_') - .replace('/', '_') - .replace(innerDelim, '_'); - } - - protected void forwardDecls(PrintWriter pw, TypeElement clazz) - throws TypeSignature.SignatureException { - TypeElement object = elems.getTypeElement("java.lang.Object"); - if (clazz.equals(object)) - return; - - genHandleType(pw, clazz.getQualifiedName().toString()); - TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass())); - - if (superClass != null) { - String superClassName = superClass.getQualifiedName().toString(); - forwardDecls(pw, superClass); - } - - for (VariableElement field: fields) { - - if (!field.getModifiers().contains(Modifier.STATIC)) { - TypeMirror t = types.erasure(field.asType()); - TypeSignature newTypeSig = new TypeSignature(elems); - String tname = newTypeSig.qualifiedTypeName(t); - String sig = newTypeSig.getTypeSignature(tname); - - if (sig.charAt(0) != '[') - forwardDeclsFromSig(pw, sig); - } - } - - for (ExecutableElement method: methods) { - - if (method.getModifiers().contains(Modifier.NATIVE)) { - TypeMirror retType = types.erasure(method.getReturnType()); - String typesig = signature(method); - TypeSignature newTypeSig = new TypeSignature(elems); - String sig = newTypeSig.getTypeSignature(typesig, retType); - - if (sig.charAt(0) != '[') - forwardDeclsFromSig(pw, sig); - - } - } - } - - protected void forwardDeclsFromSig(PrintWriter pw, String sig) { - int len = sig.length(); - int i = sig.charAt(0) == '(' ? 1 : 0; - - /* Skip the initial "(". */ - while (i < len) { - if (sig.charAt(i) == 'L') { - int j = i + 1; - while (sig.charAt(j) != ';') j++; - genHandleType(pw, sig.substring(i + 1, j)); - i = j + 1; - } else { - i++; - } - } - } - - protected void structSectionForClass(PrintWriter pw, - TypeElement jclazz, String cname) { - - String jname = jclazz.getQualifiedName().toString(); - - if (cname.equals("java_lang_Object")) { - pw.println("/* struct java_lang_Object is defined in typedefs.h. */"); - pw.println(); - return; - } - pw.println("#if !defined(__i386)"); - pw.println("#pragma pack(4)"); - pw.println("#endif"); - pw.println(); - pw.println("struct " + cname + " {"); - pw.println(" ObjHeader h;"); - pw.print(fieldDefs(jclazz, cname)); - - if (jname.equals("java.lang.Class")) - pw.println(" Class *LLNI_mask(cClass);" + - " /* Fake field; don't access (see oobj.h) */"); - pw.println("};" + lineSep + lineSep + "#pragma pack()"); - pw.println(); - return; - } - - private static class FieldDefsRes { - public String className; /* Name of the current class. */ - public FieldDefsRes parent; - public String s; - public int byteSize; - public boolean bottomMost; - public boolean printedOne = false; - - FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) { - this.className = clazz.getQualifiedName().toString(); - this.parent = parent; - this.bottomMost = bottomMost; - int byteSize = 0; - if (parent == null) this.s = ""; - else this.s = parent.s; - } - } - - /* Returns "true" iff added a field. */ - private boolean doField(FieldDefsRes res, VariableElement field, - String cname, boolean padWord) { - - String fieldDef = addStructMember(field, cname, padWord); - if (fieldDef != null) { - if (!res.printedOne) { /* add separator */ - if (res.bottomMost) { - if (res.s.length() != 0) - res.s = res.s + " /* local members: */" + lineSep; - } else { - res.s = res.s + " /* inherited members from " + - res.className + ": */" + lineSep; - } - res.printedOne = true; - } - res.s = res.s + fieldDef; - return true; - } - - // Otherwise. - return false; - } - - private int doTwoWordFields(FieldDefsRes res, TypeElement clazz, - int offset, String cname, boolean padWord) { - boolean first = true; - List fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); - - for (VariableElement field: fields) { - TypeKind tk = field.asType().getKind(); - boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); - if (twoWords && doField(res, field, cname, first && padWord)) { - offset += 8; first = false; - } - } - return offset; - } - - String fieldDefs(TypeElement clazz, String cname) { - FieldDefsRes res = fieldDefs(clazz, cname, true); - return res.s; - } - - FieldDefsRes fieldDefs(TypeElement clazz, String cname, - boolean bottomMost){ - FieldDefsRes res; - int offset; - boolean didTwoWordFields = false; - - TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass()); - - if (superclazz != null) { - String supername = superclazz.getQualifiedName().toString(); - res = new FieldDefsRes(clazz, - fieldDefs(superclazz, cname, false), - bottomMost); - offset = res.parent.byteSize; - } else { - res = new FieldDefsRes(clazz, null, bottomMost); - offset = 0; - } - - List fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); - - for (VariableElement field: fields) { - - if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) { - offset = doTwoWordFields(res, clazz, offset, cname, false); - didTwoWordFields = true; - } - - TypeKind tk = field.asType().getKind(); - boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); - - if (!doubleAlign || !twoWords) { - if (doField(res, field, cname, false)) offset += 4; - } - - } - - if (doubleAlign && !didTwoWordFields) { - if ((offset % 8) != 0) offset += 4; - offset = doTwoWordFields(res, clazz, offset, cname, true); - } - - res.byteSize = offset; - return res; - } - - /* OVERRIDE: This method handles instance fields */ - protected String addStructMember(VariableElement member, String cname, - boolean padWord) { - String res = null; - - if (member.getModifiers().contains(Modifier.STATIC)) { - res = addStaticStructMember(member, cname); - // if (res == null) /* JNI didn't handle it, print comment. */ - // res = " /* Inaccessible static: " + member + " */" + lineSep; - } else { - TypeMirror mt = types.erasure(member.asType()); - if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep; - res = " " + llniType(mt, false, false) + " " + llniFieldName(member); - if (isLongOrDouble(mt)) res = res + "[2]"; - res = res + ";" + lineSep; - } - return res; - } - - static private final boolean isWindows = - System.getProperty("os.name").startsWith("Windows"); - - /* - * This method only handles static final fields. - */ - protected String addStaticStructMember(VariableElement field, String cname) { - String res = null; - Object exp = null; - - if (!field.getModifiers().contains(Modifier.STATIC)) - return res; - if (!field.getModifiers().contains(Modifier.FINAL)) - return res; - - exp = field.getConstantValue(); - - if (exp != null) { - /* Constant. */ - - String cn = cname + "_" + field.getSimpleName(); - String suffix = null; - long val = 0; - /* Can only handle int, long, float, and double fields. */ - if (exp instanceof Byte - || exp instanceof Short - || exp instanceof Integer) { - suffix = "L"; - val = ((Number)exp).intValue(); - } - else if (exp instanceof Long) { - // Visual C++ supports the i64 suffix, not LL - suffix = isWindows ? "i64" : "LL"; - val = ((Long)exp).longValue(); - } - else if (exp instanceof Float) suffix = "f"; - else if (exp instanceof Double) suffix = ""; - else if (exp instanceof Character) { - suffix = "L"; - Character ch = (Character) exp; - val = ((int) ch) & 0xffff; - } - if (suffix != null) { - // Some compilers will generate a spurious warning - // for the integer constants for Integer.MIN_VALUE - // and Long.MIN_VALUE so we handle them specially. - if ((suffix.equals("L") && (val == Integer.MIN_VALUE)) || - (suffix.equals("LL") && (val == Long.MIN_VALUE))) { - res = " #undef " + cn + lineSep - + " #define " + cn - + " (" + (val + 1) + suffix + "-1)" + lineSep; - } else if (suffix.equals("L") || suffix.endsWith("LL")) { - res = " #undef " + cn + lineSep - + " #define " + cn + " " + val + suffix + lineSep; - } else { - res = " #undef " + cn + lineSep - + " #define " + cn + " " + exp + suffix + lineSep; - } - } - } - return res; - } - - protected void methodSectionForClass(PrintWriter pw, - TypeElement clazz, String cname) - throws TypeSignature.SignatureException, Util.Exit { - String methods = methodDecls(clazz, cname); - - if (methods.length() != 0) { - pw.println("/* Native method declarations: */" + lineSep); - pw.println("#ifdef __cplusplus"); - pw.println("extern \"C\" {"); - pw.println("#endif" + lineSep); - pw.println(methods); - pw.println("#ifdef __cplusplus"); - pw.println("}"); - pw.println("#endif"); - } - } - - protected String methodDecls(TypeElement clazz, String cname) - throws TypeSignature.SignatureException, Util.Exit { - - String res = ""; - for (ExecutableElement method: methods) { - if (method.getModifiers().contains(Modifier.NATIVE)) - res = res + methodDecl(method, clazz, cname); - } - return res; - } - - protected String methodDecl(ExecutableElement method, - TypeElement clazz, String cname) - throws TypeSignature.SignatureException, Util.Exit { - String res = null; - - TypeMirror retType = types.erasure(method.getReturnType()); - String typesig = signature(method); - TypeSignature newTypeSig = new TypeSignature(elems); - String sig = newTypeSig.getTypeSignature(typesig, retType); - boolean longName = needLongName(method, clazz); - - if (sig.charAt(0) != '(') - util.error("invalid.method.signature", sig); - - - res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName) - + "(JNIEnv *, " + cRcvrDecl(method, cname); - List params = method.getParameters(); - List argTypes = new ArrayList<>(); - for (VariableElement p: params){ - argTypes.add(types.erasure(p.asType())); - } - - /* It would have been nice to include the argument names in the - declaration, but there seems to be a bug in the "BinaryField" - class, causing the getArguments() method to return "null" for - most (non-constructor) methods. */ - for (TypeMirror argType: argTypes) - res = res + ", " + jniType(argType); - res = res + ");" + lineSep; - return res; - } - - protected final boolean needLongName(ExecutableElement method, - TypeElement clazz) { - Name methodName = method.getSimpleName(); - for (ExecutableElement memberMethod: methods) { - if ((memberMethod != method) && - memberMethod.getModifiers().contains(Modifier.NATIVE) && - (methodName.equals(memberMethod.getSimpleName()))) - return true; - } - return false; - } - - protected final String jniMethodName(ExecutableElement method, String cname, - boolean longName) - throws TypeSignature.SignatureException { - String res = "Java_" + cname + "_" + method.getSimpleName(); - - if (longName) { - TypeMirror mType = types.erasure(method.getReturnType()); - List params = method.getParameters(); - List argTypes = new ArrayList<>(); - for (VariableElement param: params) { - argTypes.add(types.erasure(param.asType())); - } - - res = res + "__"; - for (TypeMirror t: argTypes) { - String tname = t.toString(); - TypeSignature newTypeSig = new TypeSignature(elems); - String sig = newTypeSig.getTypeSignature(tname); - res = res + nameToIdentifier(sig); - } - } - return res; - } - - // copied from JNI.java - protected final String jniType(TypeMirror t) throws Util.Exit { - TypeElement throwable = elems.getTypeElement("java.lang.Throwable"); - TypeElement jClass = elems.getTypeElement("java.lang.Class"); - TypeElement jString = elems.getTypeElement("java.lang.String"); - Element tclassDoc = types.asElement(t); - - switch (t.getKind()) { - case ARRAY: { - TypeMirror ct = ((ArrayType) t).getComponentType(); - switch (ct.getKind()) { - case BOOLEAN: return "jbooleanArray"; - case BYTE: return "jbyteArray"; - case CHAR: return "jcharArray"; - case SHORT: return "jshortArray"; - case INT: return "jintArray"; - case LONG: return "jlongArray"; - case FLOAT: return "jfloatArray"; - case DOUBLE: return "jdoubleArray"; - case ARRAY: - case DECLARED: return "jobjectArray"; - default: throw new Error(ct.toString()); - } - } - - case VOID: return "void"; - case BOOLEAN: return "jboolean"; - case BYTE: return "jbyte"; - case CHAR: return "jchar"; - case SHORT: return "jshort"; - case INT: return "jint"; - case LONG: return "jlong"; - case FLOAT: return "jfloat"; - case DOUBLE: return "jdouble"; - - case DECLARED: { - if (tclassDoc.equals(jString)) - return "jstring"; - else if (types.isAssignable(t, throwable.asType())) - return "jthrowable"; - else if (types.isAssignable(t, jClass.asType())) - return "jclass"; - else - return "jobject"; - } - } - - util.bug("jni.unknown.type"); - return null; /* dead code. */ - } - - protected String llniType(TypeMirror t, boolean handleize, boolean longDoubleOK) { - String res = null; - - switch (t.getKind()) { - case ARRAY: { - TypeMirror ct = ((ArrayType) t).getComponentType(); - switch (ct.getKind()) { - case BOOLEAN: res = "IArrayOfBoolean"; break; - case BYTE: res = "IArrayOfByte"; break; - case CHAR: res = "IArrayOfChar"; break; - case SHORT: res = "IArrayOfShort"; break; - case INT: res = "IArrayOfInt"; break; - case LONG: res = "IArrayOfLong"; break; - case FLOAT: res = "IArrayOfFloat"; break; - case DOUBLE: res = "IArrayOfDouble"; break; - case ARRAY: - case DECLARED: res = "IArrayOfRef"; break; - default: throw new Error(ct.getKind() + " " + ct); - } - if (!handleize) res = "DEREFERENCED_" + res; - break; - } - - case VOID: - res = "void"; - break; - - case BOOLEAN: - case BYTE: - case CHAR: - case SHORT: - case INT: - res = "java_int" ; - break; - - case LONG: - res = longDoubleOK ? "java_long" : "val32 /* java_long */"; - break; - - case FLOAT: - res = "java_float"; - break; - - case DOUBLE: - res = longDoubleOK ? "java_double" : "val32 /* java_double */"; - break; - - case DECLARED: - TypeElement e = (TypeElement) types.asElement(t); - res = "I" + mangleClassName(e.getQualifiedName().toString()); - if (!handleize) res = "DEREFERENCED_" + res; - break; - - default: - throw new Error(t.getKind() + " " + t); // FIXME - } - - return res; - } - - protected final String cRcvrDecl(Element field, String cname) { - return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject"); - } - - protected String maskName(String s) { - return "LLNI_mask(" + s + ")"; - } - - protected String llniFieldName(VariableElement field) { - return maskName(field.getSimpleName().toString()); - } - - protected final boolean isLongOrDouble(TypeMirror t) { - TypeVisitor v = new SimpleTypeVisitor9() { - @DefinedBy(Api.LANGUAGE_MODEL) - public Boolean defaultAction(TypeMirror t, Void p){ - return false; - } - @DefinedBy(Api.LANGUAGE_MODEL) - public Boolean visitArray(ArrayType t, Void p) { - return visit(t.getComponentType(), p); - } - @DefinedBy(Api.LANGUAGE_MODEL) - public Boolean visitPrimitive(PrimitiveType t, Void p) { - TypeKind tk = t.getKind(); - return (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); - } - }; - return v.visit(t, null); - } - - /* Do unicode to ansi C identifier conversion. - %%% This may not be right, but should be called more often. */ - protected final String nameToIdentifier(String name) { - int len = name.length(); - StringBuilder buf = new StringBuilder(len); - for (int i = 0; i < len; i++) { - char c = name.charAt(i); - if (isASCIILetterOrDigit(c)) - buf.append(c); - else if (c == '/') - buf.append('_'); - else if (c == '.') - buf.append('_'); - else if (c == '_') - buf.append("_1"); - else if (c == ';') - buf.append("_2"); - else if (c == '[') - buf.append("_3"); - else - buf.append("_0" + ((int)c)); - } - return new String(buf); - } - - protected final boolean isASCIILetterOrDigit(char c) { - if (((c >= 'A') && (c <= 'Z')) || - ((c >= 'a') && (c <= 'z')) || - ((c >= '0') && (c <= '9'))) - return true; - else - return false; - } -} -