Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javah/LLNI.java
38899 views
1
/*
2
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
27
package com.sun.tools.javah;
28
29
import java.io.OutputStream;
30
import java.io.PrintWriter;
31
import java.util.ArrayList;
32
import java.util.HashSet;
33
import java.util.List;
34
35
import java.util.Set;
36
import javax.lang.model.element.Element;
37
import javax.lang.model.element.ExecutableElement;
38
import javax.lang.model.element.Modifier;
39
import javax.lang.model.element.Name;
40
import javax.lang.model.element.TypeElement;
41
import javax.lang.model.element.VariableElement;
42
import javax.lang.model.type.ArrayType;
43
import javax.lang.model.type.PrimitiveType;
44
import javax.lang.model.type.TypeKind;
45
import javax.lang.model.type.TypeMirror;
46
import javax.lang.model.type.TypeVisitor;
47
import javax.lang.model.util.ElementFilter;
48
import javax.lang.model.util.SimpleTypeVisitor8;
49
50
/*
51
* <p><b>This is NOT part of any supported API.
52
* If you write code that depends on this, you do so at your own
53
* risk. This code and its internal interfaces are subject to change
54
* or deletion without notice.</b></p>
55
*
56
* @author Sucheta Dambalkar(Revised)
57
*/
58
public class LLNI extends Gen {
59
60
protected final char innerDelim = '$'; /* For inner classes */
61
protected Set<String> doneHandleTypes;
62
List<VariableElement> fields;
63
List<ExecutableElement> methods;
64
private boolean doubleAlign;
65
private int padFieldNum = 0;
66
67
LLNI(boolean doubleAlign, Util util) {
68
super(util);
69
this.doubleAlign = doubleAlign;
70
}
71
72
protected String getIncludes() {
73
return "";
74
}
75
76
protected void write(OutputStream o, TypeElement clazz) throws Util.Exit {
77
try {
78
String cname = mangleClassName(clazz.getQualifiedName().toString());
79
PrintWriter pw = wrapWriter(o);
80
fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
81
methods = ElementFilter.methodsIn(clazz.getEnclosedElements());
82
generateDeclsForClass(pw, clazz, cname);
83
// FIXME check if errors occurred on the PrintWriter and throw exception if so
84
} catch (TypeSignature.SignatureException e) {
85
util.error("llni.sigerror", e.getMessage());
86
}
87
}
88
89
protected void generateDeclsForClass(PrintWriter pw,
90
TypeElement clazz, String cname)
91
throws TypeSignature.SignatureException, Util.Exit {
92
doneHandleTypes = new HashSet<String>();
93
/* The following handle types are predefined in "typedefs.h". Suppress
94
inclusion in the output by generating them "into the blue" here. */
95
genHandleType(null, "java.lang.Class");
96
genHandleType(null, "java.lang.ClassLoader");
97
genHandleType(null, "java.lang.Object");
98
genHandleType(null, "java.lang.String");
99
genHandleType(null, "java.lang.Thread");
100
genHandleType(null, "java.lang.ThreadGroup");
101
genHandleType(null, "java.lang.Throwable");
102
103
pw.println("/* LLNI Header for class " + clazz.getQualifiedName() + " */" + lineSep);
104
pw.println("#ifndef _Included_" + cname);
105
pw.println("#define _Included_" + cname);
106
pw.println("#include \"typedefs.h\"");
107
pw.println("#include \"llni.h\"");
108
pw.println("#include \"jni.h\"" + lineSep);
109
110
forwardDecls(pw, clazz);
111
structSectionForClass(pw, clazz, cname);
112
methodSectionForClass(pw, clazz, cname);
113
pw.println("#endif");
114
}
115
116
protected void genHandleType(PrintWriter pw, String clazzname) {
117
String cname = mangleClassName(clazzname);
118
if (!doneHandleTypes.contains(cname)) {
119
doneHandleTypes.add(cname);
120
if (pw != null) {
121
pw.println("#ifndef DEFINED_" + cname);
122
pw.println(" #define DEFINED_" + cname);
123
pw.println(" GEN_HANDLE_TYPES(" + cname + ");");
124
pw.println("#endif" + lineSep);
125
}
126
}
127
}
128
129
protected String mangleClassName(String s) {
130
return s.replace('.', '_')
131
.replace('/', '_')
132
.replace(innerDelim, '_');
133
}
134
135
protected void forwardDecls(PrintWriter pw, TypeElement clazz)
136
throws TypeSignature.SignatureException {
137
TypeElement object = elems.getTypeElement("java.lang.Object");
138
if (clazz.equals(object))
139
return;
140
141
genHandleType(pw, clazz.getQualifiedName().toString());
142
TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass()));
143
144
if (superClass != null) {
145
String superClassName = superClass.getQualifiedName().toString();
146
forwardDecls(pw, superClass);
147
}
148
149
for (VariableElement field: fields) {
150
151
if (!field.getModifiers().contains(Modifier.STATIC)) {
152
TypeMirror t = types.erasure(field.asType());
153
TypeSignature newTypeSig = new TypeSignature(elems);
154
String tname = newTypeSig.qualifiedTypeName(t);
155
String sig = newTypeSig.getTypeSignature(tname);
156
157
if (sig.charAt(0) != '[')
158
forwardDeclsFromSig(pw, sig);
159
}
160
}
161
162
for (ExecutableElement method: methods) {
163
164
if (method.getModifiers().contains(Modifier.NATIVE)) {
165
TypeMirror retType = types.erasure(method.getReturnType());
166
String typesig = signature(method);
167
TypeSignature newTypeSig = new TypeSignature(elems);
168
String sig = newTypeSig.getTypeSignature(typesig, retType);
169
170
if (sig.charAt(0) != '[')
171
forwardDeclsFromSig(pw, sig);
172
173
}
174
}
175
}
176
177
protected void forwardDeclsFromSig(PrintWriter pw, String sig) {
178
int len = sig.length();
179
int i = sig.charAt(0) == '(' ? 1 : 0;
180
181
/* Skip the initial "(". */
182
while (i < len) {
183
if (sig.charAt(i) == 'L') {
184
int j = i + 1;
185
while (sig.charAt(j) != ';') j++;
186
genHandleType(pw, sig.substring(i + 1, j));
187
i = j + 1;
188
} else {
189
i++;
190
}
191
}
192
}
193
194
protected void structSectionForClass(PrintWriter pw,
195
TypeElement jclazz, String cname) {
196
197
String jname = jclazz.getQualifiedName().toString();
198
199
if (cname.equals("java_lang_Object")) {
200
pw.println("/* struct java_lang_Object is defined in typedefs.h. */");
201
pw.println();
202
return;
203
}
204
pw.println("#if !defined(__i386)");
205
pw.println("#pragma pack(4)");
206
pw.println("#endif");
207
pw.println();
208
pw.println("struct " + cname + " {");
209
pw.println(" ObjHeader h;");
210
pw.print(fieldDefs(jclazz, cname));
211
212
if (jname.equals("java.lang.Class"))
213
pw.println(" Class *LLNI_mask(cClass);" +
214
" /* Fake field; don't access (see oobj.h) */");
215
pw.println("};" + lineSep + lineSep + "#pragma pack()");
216
pw.println();
217
return;
218
}
219
220
private static class FieldDefsRes {
221
public String className; /* Name of the current class. */
222
public FieldDefsRes parent;
223
public String s;
224
public int byteSize;
225
public boolean bottomMost;
226
public boolean printedOne = false;
227
228
FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) {
229
this.className = clazz.getQualifiedName().toString();
230
this.parent = parent;
231
this.bottomMost = bottomMost;
232
int byteSize = 0;
233
if (parent == null) this.s = "";
234
else this.s = parent.s;
235
}
236
}
237
238
/* Returns "true" iff added a field. */
239
private boolean doField(FieldDefsRes res, VariableElement field,
240
String cname, boolean padWord) {
241
242
String fieldDef = addStructMember(field, cname, padWord);
243
if (fieldDef != null) {
244
if (!res.printedOne) { /* add separator */
245
if (res.bottomMost) {
246
if (res.s.length() != 0)
247
res.s = res.s + " /* local members: */" + lineSep;
248
} else {
249
res.s = res.s + " /* inherited members from " +
250
res.className + ": */" + lineSep;
251
}
252
res.printedOne = true;
253
}
254
res.s = res.s + fieldDef;
255
return true;
256
}
257
258
// Otherwise.
259
return false;
260
}
261
262
private int doTwoWordFields(FieldDefsRes res, TypeElement clazz,
263
int offset, String cname, boolean padWord) {
264
boolean first = true;
265
List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
266
267
for (VariableElement field: fields) {
268
TypeKind tk = field.asType().getKind();
269
boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
270
if (twoWords && doField(res, field, cname, first && padWord)) {
271
offset += 8; first = false;
272
}
273
}
274
return offset;
275
}
276
277
String fieldDefs(TypeElement clazz, String cname) {
278
FieldDefsRes res = fieldDefs(clazz, cname, true);
279
return res.s;
280
}
281
282
FieldDefsRes fieldDefs(TypeElement clazz, String cname,
283
boolean bottomMost){
284
FieldDefsRes res;
285
int offset;
286
boolean didTwoWordFields = false;
287
288
TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass());
289
290
if (superclazz != null) {
291
String supername = superclazz.getQualifiedName().toString();
292
res = new FieldDefsRes(clazz,
293
fieldDefs(superclazz, cname, false),
294
bottomMost);
295
offset = res.parent.byteSize;
296
} else {
297
res = new FieldDefsRes(clazz, null, bottomMost);
298
offset = 0;
299
}
300
301
List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
302
303
for (VariableElement field: fields) {
304
305
if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) {
306
offset = doTwoWordFields(res, clazz, offset, cname, false);
307
didTwoWordFields = true;
308
}
309
310
TypeKind tk = field.asType().getKind();
311
boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
312
313
if (!doubleAlign || !twoWords) {
314
if (doField(res, field, cname, false)) offset += 4;
315
}
316
317
}
318
319
if (doubleAlign && !didTwoWordFields) {
320
if ((offset % 8) != 0) offset += 4;
321
offset = doTwoWordFields(res, clazz, offset, cname, true);
322
}
323
324
res.byteSize = offset;
325
return res;
326
}
327
328
/* OVERRIDE: This method handles instance fields */
329
protected String addStructMember(VariableElement member, String cname,
330
boolean padWord) {
331
String res = null;
332
333
if (member.getModifiers().contains(Modifier.STATIC)) {
334
res = addStaticStructMember(member, cname);
335
// if (res == null) /* JNI didn't handle it, print comment. */
336
// res = " /* Inaccessible static: " + member + " */" + lineSep;
337
} else {
338
TypeMirror mt = types.erasure(member.asType());
339
if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep;
340
res = " " + llniType(mt, false, false) + " " + llniFieldName(member);
341
if (isLongOrDouble(mt)) res = res + "[2]";
342
res = res + ";" + lineSep;
343
}
344
return res;
345
}
346
347
static private final boolean isWindows =
348
System.getProperty("os.name").startsWith("Windows");
349
350
/*
351
* This method only handles static final fields.
352
*/
353
protected String addStaticStructMember(VariableElement field, String cname) {
354
String res = null;
355
Object exp = null;
356
357
if (!field.getModifiers().contains(Modifier.STATIC))
358
return res;
359
if (!field.getModifiers().contains(Modifier.FINAL))
360
return res;
361
362
exp = field.getConstantValue();
363
364
if (exp != null) {
365
/* Constant. */
366
367
String cn = cname + "_" + field.getSimpleName();
368
String suffix = null;
369
long val = 0;
370
/* Can only handle int, long, float, and double fields. */
371
if (exp instanceof Byte
372
|| exp instanceof Short
373
|| exp instanceof Integer) {
374
suffix = "L";
375
val = ((Number)exp).intValue();
376
}
377
else if (exp instanceof Long) {
378
// Visual C++ supports the i64 suffix, not LL
379
suffix = isWindows ? "i64" : "LL";
380
val = ((Long)exp).longValue();
381
}
382
else if (exp instanceof Float) suffix = "f";
383
else if (exp instanceof Double) suffix = "";
384
else if (exp instanceof Character) {
385
suffix = "L";
386
Character ch = (Character) exp;
387
val = ((int) ch) & 0xffff;
388
}
389
if (suffix != null) {
390
// Some compilers will generate a spurious warning
391
// for the integer constants for Integer.MIN_VALUE
392
// and Long.MIN_VALUE so we handle them specially.
393
if ((suffix.equals("L") && (val == Integer.MIN_VALUE)) ||
394
(suffix.equals("LL") && (val == Long.MIN_VALUE))) {
395
res = " #undef " + cn + lineSep
396
+ " #define " + cn
397
+ " (" + (val + 1) + suffix + "-1)" + lineSep;
398
} else if (suffix.equals("L") || suffix.endsWith("LL")) {
399
res = " #undef " + cn + lineSep
400
+ " #define " + cn + " " + val + suffix + lineSep;
401
} else {
402
res = " #undef " + cn + lineSep
403
+ " #define " + cn + " " + exp + suffix + lineSep;
404
}
405
}
406
}
407
return res;
408
}
409
410
protected void methodSectionForClass(PrintWriter pw,
411
TypeElement clazz, String cname)
412
throws TypeSignature.SignatureException, Util.Exit {
413
String methods = methodDecls(clazz, cname);
414
415
if (methods.length() != 0) {
416
pw.println("/* Native method declarations: */" + lineSep);
417
pw.println("#ifdef __cplusplus");
418
pw.println("extern \"C\" {");
419
pw.println("#endif" + lineSep);
420
pw.println(methods);
421
pw.println("#ifdef __cplusplus");
422
pw.println("}");
423
pw.println("#endif");
424
}
425
}
426
427
protected String methodDecls(TypeElement clazz, String cname)
428
throws TypeSignature.SignatureException, Util.Exit {
429
430
String res = "";
431
for (ExecutableElement method: methods) {
432
if (method.getModifiers().contains(Modifier.NATIVE))
433
res = res + methodDecl(method, clazz, cname);
434
}
435
return res;
436
}
437
438
protected String methodDecl(ExecutableElement method,
439
TypeElement clazz, String cname)
440
throws TypeSignature.SignatureException, Util.Exit {
441
String res = null;
442
443
TypeMirror retType = types.erasure(method.getReturnType());
444
String typesig = signature(method);
445
TypeSignature newTypeSig = new TypeSignature(elems);
446
String sig = newTypeSig.getTypeSignature(typesig, retType);
447
boolean longName = needLongName(method, clazz);
448
449
if (sig.charAt(0) != '(')
450
util.error("invalid.method.signature", sig);
451
452
453
res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName)
454
+ "(JNIEnv *, " + cRcvrDecl(method, cname);
455
List<? extends VariableElement> params = method.getParameters();
456
List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
457
for (VariableElement p: params){
458
argTypes.add(types.erasure(p.asType()));
459
}
460
461
/* It would have been nice to include the argument names in the
462
declaration, but there seems to be a bug in the "BinaryField"
463
class, causing the getArguments() method to return "null" for
464
most (non-constructor) methods. */
465
for (TypeMirror argType: argTypes)
466
res = res + ", " + jniType(argType);
467
res = res + ");" + lineSep;
468
return res;
469
}
470
471
protected final boolean needLongName(ExecutableElement method,
472
TypeElement clazz) {
473
Name methodName = method.getSimpleName();
474
for (ExecutableElement memberMethod: methods) {
475
if ((memberMethod != method) &&
476
memberMethod.getModifiers().contains(Modifier.NATIVE) &&
477
(methodName.equals(memberMethod.getSimpleName())))
478
return true;
479
}
480
return false;
481
}
482
483
protected final String jniMethodName(ExecutableElement method, String cname,
484
boolean longName)
485
throws TypeSignature.SignatureException {
486
String res = "Java_" + cname + "_" + method.getSimpleName();
487
488
if (longName) {
489
TypeMirror mType = types.erasure(method.getReturnType());
490
List<? extends VariableElement> params = method.getParameters();
491
List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
492
for (VariableElement param: params) {
493
argTypes.add(types.erasure(param.asType()));
494
}
495
496
res = res + "__";
497
for (TypeMirror t: argTypes) {
498
String tname = t.toString();
499
TypeSignature newTypeSig = new TypeSignature(elems);
500
String sig = newTypeSig.getTypeSignature(tname);
501
res = res + nameToIdentifier(sig);
502
}
503
}
504
return res;
505
}
506
507
// copied from JNI.java
508
protected final String jniType(TypeMirror t) throws Util.Exit {
509
TypeElement throwable = elems.getTypeElement("java.lang.Throwable");
510
TypeElement jClass = elems.getTypeElement("java.lang.Class");
511
TypeElement jString = elems.getTypeElement("java.lang.String");
512
Element tclassDoc = types.asElement(t);
513
514
switch (t.getKind()) {
515
case ARRAY: {
516
TypeMirror ct = ((ArrayType) t).getComponentType();
517
switch (ct.getKind()) {
518
case BOOLEAN: return "jbooleanArray";
519
case BYTE: return "jbyteArray";
520
case CHAR: return "jcharArray";
521
case SHORT: return "jshortArray";
522
case INT: return "jintArray";
523
case LONG: return "jlongArray";
524
case FLOAT: return "jfloatArray";
525
case DOUBLE: return "jdoubleArray";
526
case ARRAY:
527
case DECLARED: return "jobjectArray";
528
default: throw new Error(ct.toString());
529
}
530
}
531
532
case VOID: return "void";
533
case BOOLEAN: return "jboolean";
534
case BYTE: return "jbyte";
535
case CHAR: return "jchar";
536
case SHORT: return "jshort";
537
case INT: return "jint";
538
case LONG: return "jlong";
539
case FLOAT: return "jfloat";
540
case DOUBLE: return "jdouble";
541
542
case DECLARED: {
543
if (tclassDoc.equals(jString))
544
return "jstring";
545
else if (types.isAssignable(t, throwable.asType()))
546
return "jthrowable";
547
else if (types.isAssignable(t, jClass.asType()))
548
return "jclass";
549
else
550
return "jobject";
551
}
552
}
553
554
util.bug("jni.unknown.type");
555
return null; /* dead code. */
556
}
557
558
protected String llniType(TypeMirror t, boolean handleize, boolean longDoubleOK) {
559
String res = null;
560
561
switch (t.getKind()) {
562
case ARRAY: {
563
TypeMirror ct = ((ArrayType) t).getComponentType();
564
switch (ct.getKind()) {
565
case BOOLEAN: res = "IArrayOfBoolean"; break;
566
case BYTE: res = "IArrayOfByte"; break;
567
case CHAR: res = "IArrayOfChar"; break;
568
case SHORT: res = "IArrayOfShort"; break;
569
case INT: res = "IArrayOfInt"; break;
570
case LONG: res = "IArrayOfLong"; break;
571
case FLOAT: res = "IArrayOfFloat"; break;
572
case DOUBLE: res = "IArrayOfDouble"; break;
573
case ARRAY:
574
case DECLARED: res = "IArrayOfRef"; break;
575
default: throw new Error(ct.getKind() + " " + ct);
576
}
577
if (!handleize) res = "DEREFERENCED_" + res;
578
break;
579
}
580
581
case VOID:
582
res = "void";
583
break;
584
585
case BOOLEAN:
586
case BYTE:
587
case CHAR:
588
case SHORT:
589
case INT:
590
res = "java_int" ;
591
break;
592
593
case LONG:
594
res = longDoubleOK ? "java_long" : "val32 /* java_long */";
595
break;
596
597
case FLOAT:
598
res = "java_float";
599
break;
600
601
case DOUBLE:
602
res = longDoubleOK ? "java_double" : "val32 /* java_double */";
603
break;
604
605
case DECLARED:
606
TypeElement e = (TypeElement) types.asElement(t);
607
res = "I" + mangleClassName(e.getQualifiedName().toString());
608
if (!handleize) res = "DEREFERENCED_" + res;
609
break;
610
611
default:
612
throw new Error(t.getKind() + " " + t); // FIXME
613
}
614
615
return res;
616
}
617
618
protected final String cRcvrDecl(Element field, String cname) {
619
return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject");
620
}
621
622
protected String maskName(String s) {
623
return "LLNI_mask(" + s + ")";
624
}
625
626
protected String llniFieldName(VariableElement field) {
627
return maskName(field.getSimpleName().toString());
628
}
629
630
protected final boolean isLongOrDouble(TypeMirror t) {
631
TypeVisitor<Boolean,Void> v = new SimpleTypeVisitor8<Boolean,Void>() {
632
public Boolean defaultAction(TypeMirror t, Void p){
633
return false;
634
}
635
public Boolean visitArray(ArrayType t, Void p) {
636
return visit(t.getComponentType(), p);
637
}
638
public Boolean visitPrimitive(PrimitiveType t, Void p) {
639
TypeKind tk = t.getKind();
640
return (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
641
}
642
};
643
return v.visit(t, null);
644
}
645
646
/* Do unicode to ansi C identifier conversion.
647
%%% This may not be right, but should be called more often. */
648
protected final String nameToIdentifier(String name) {
649
int len = name.length();
650
StringBuilder buf = new StringBuilder(len);
651
for (int i = 0; i < len; i++) {
652
char c = name.charAt(i);
653
if (isASCIILetterOrDigit(c))
654
buf.append(c);
655
else if (c == '/')
656
buf.append('_');
657
else if (c == '.')
658
buf.append('_');
659
else if (c == '_')
660
buf.append("_1");
661
else if (c == ';')
662
buf.append("_2");
663
else if (c == '[')
664
buf.append("_3");
665
else
666
buf.append("_0" + ((int)c));
667
}
668
return new String(buf);
669
}
670
671
protected final boolean isASCIILetterOrDigit(char c) {
672
if (((c >= 'A') && (c <= 'Z')) ||
673
((c >= 'a') && (c <= 'z')) ||
674
((c >= '0') && (c <= '9')))
675
return true;
676
else
677
return false;
678
}
679
}
680
681
682