23 * questions.
24 */
25
26 package com.sun.tools.javac.jvm;
27
28 import java.io.*;
29 import java.util.LinkedHashMap;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.LinkedHashSet;
33 import java.util.function.ToIntFunction;
34
35 import javax.tools.JavaFileManager;
36 import javax.tools.FileObject;
37 import javax.tools.JavaFileManager.Location;
38 import javax.tools.JavaFileObject;
39
40 import com.sun.tools.javac.code.*;
41 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
42 import com.sun.tools.javac.code.Directive.*;
43 import com.sun.tools.javac.code.Source.Feature;
44 import com.sun.tools.javac.code.Symbol.*;
45 import com.sun.tools.javac.code.Type.*;
46 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
47 import com.sun.tools.javac.comp.Check;
48 import com.sun.tools.javac.file.PathFileObject;
49 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
50 import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
51 import com.sun.tools.javac.resources.CompilerProperties.Errors;
52 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
53 import com.sun.tools.javac.util.*;
54 import com.sun.tools.javac.util.List;
55
56 import static com.sun.tools.javac.code.Flags.*;
57 import static com.sun.tools.javac.code.Kinds.Kind.*;
58 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
59 import static com.sun.tools.javac.code.TypeTag.*;
60 import static com.sun.tools.javac.main.Option.*;
61
62 import static javax.tools.StandardLocation.CLASS_OUTPUT;
125
126 /** An output buffer for member info.
127 */
128 public ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
129
130 /** An output buffer for the constant pool.
131 */
132 ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
133
134 /** The constant pool writer.
135 */
136 final PoolWriter poolWriter;
137
138 /** The log to use for verbose output.
139 */
140 private final Log log;
141
142 /** The name table. */
143 private final Names names;
144
145 /** Access to files. */
146 private final JavaFileManager fileManager;
147
148 /** The tags and constants used in compressed stackmap. */
149 static final int SAME_FRAME_SIZE = 64;
150 static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
151 static final int SAME_FRAME_EXTENDED = 251;
152 static final int FULL_FRAME = 255;
153 static final int MAX_LOCAL_LENGTH_DIFF = 4;
154
155 /** Get the ClassWriter instance for this context. */
156 public static ClassWriter instance(Context context) {
157 ClassWriter instance = context.get(classWriterKey);
158 if (instance == null)
159 instance = new ClassWriter(context);
160 return instance;
161 }
162
163 /** Construct a class writer, given an options table.
164 */
165 protected ClassWriter(Context context) {
166 context.put(classWriterKey, this);
167
168 log = Log.instance(context);
169 names = Names.instance(context);
170 options = Options.instance(context);
171 preview = Preview.instance(context);
172 target = Target.instance(context);
173 source = Source.instance(context);
174 types = Types.instance(context);
175 check = Check.instance(context);
176 fileManager = context.get(JavaFileManager.class);
177 poolWriter = Gen.instance(context).poolWriter;
178
179 verbose = options.isSet(VERBOSE);
180 genCrt = options.isSet(XJCOV);
181 debugstackmap = options.isSet("debug.stackmap");
182
183 emitSourceFile = options.isUnset(G_CUSTOM) ||
184 options.isSet(G_CUSTOM, "source");
185
186 String modifierFlags = options.get("debug.dumpmodifiers");
187 if (modifierFlags != null) {
188 dumpClassModifiers = modifierFlags.indexOf('c') != -1;
189 dumpFieldModifiers = modifierFlags.indexOf('f') != -1;
190 dumpInnerClassModifiers = modifierFlags.indexOf('i') != -1;
191 dumpMethodModifiers = modifierFlags.indexOf('m') != -1;
192 }
193 }
194
195 public void addExtraAttributes(ToIntFunction<Symbol> addExtraAttributes) {
196 extraAttributeHooks = extraAttributeHooks.prepend(addExtraAttributes);
197 }
198
199 /******************************************************************
200 * Diagnostics: dump generated class names and modifiers
201 ******************************************************************/
202
203 /** Value of option 'dumpmodifiers' is a string
204 * indicating which modifiers should be dumped for debugging:
205 * 'c' -- classes
206 * 'f' -- fields
207 * 'i' -- innerclass attributes
208 * 'm' -- methods
209 * For example, to dump everything:
210 * javac -XDdumpmodifiers=cifm MyProg.java
211 */
212 private boolean dumpClassModifiers; // -XDdumpmodifiers=c
213 private boolean dumpFieldModifiers; // -XDdumpmodifiers=f
214 private boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i
215 private boolean dumpMethodModifiers; // -XDdumpmodifiers=m
216
217
218 /** Return flags as a string, separated by " ".
219 */
220 public static String flagNames(long flags) {
221 StringBuilder sbuf = new StringBuilder();
222 int i = 0;
223 long f = flags & StandardFlags;
224 while (f != 0) {
225 if ((f & 1) != 0) {
226 sbuf.append(" ");
227 sbuf.append(flagName[i]);
228 }
229 f = f >> 1;
230 i++;
231 }
232 return sbuf.toString();
233 }
234 //where
235 private static final String[] flagName = {
236 "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL",
237 "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE",
238 "ABSTRACT", "STRICTFP"};
239
240 /******************************************************************
241 * Output routines
242 ******************************************************************/
243
244 /** Write a character into given byte buffer;
245 * byte buffer will not be grown.
246 */
247 void putChar(ByteBuffer buf, int op, int x) {
248 buf.elems[op ] = (byte)((x >> 8) & 0xFF);
249 buf.elems[op+1] = (byte)((x ) & 0xFF);
250 }
251
252 /** Write an integer into given byte buffer;
253 * byte buffer will not be grown.
254 */
255 void putInt(ByteBuffer buf, int adr, int x) {
256 buf.elems[adr ] = (byte)((x >> 24) & 0xFF);
257 buf.elems[adr+1] = (byte)((x >> 16) & 0xFF);
808 databuf.appendChar(poolWriter.putClass(srvc));
809 databuf.appendChar(impls.size());
810 impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
811 });
812
813 endAttr(alenIdx);
814 return 1;
815 }
816
817 /**********************************************************************
818 * Writing Objects
819 **********************************************************************/
820
821 /** Write "inner classes" attribute.
822 */
823 void writeInnerClasses() {
824 int alenIdx = writeAttr(names.InnerClasses);
825 databuf.appendChar(poolWriter.innerClasses.size());
826 for (ClassSymbol inner : poolWriter.innerClasses) {
827 inner.markAbstractIfNeeded(types);
828 char flags = (char) adjustFlags(inner.flags_field);
829 if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
830 flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.
831 if (dumpInnerClassModifiers) {
832 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
833 pw.println("INNERCLASS " + inner.name);
834 pw.println("---" + flagNames(flags));
835 }
836 databuf.appendChar(poolWriter.putClass(inner));
837 databuf.appendChar(
838 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
839 databuf.appendChar(
840 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
841 databuf.appendChar(flags);
842 }
843 endAttr(alenIdx);
844 }
845
846 int writeRecordAttribute(ClassSymbol csym) {
847 int alenIdx = writeAttr(names.Record);
848 Scope s = csym.members();
849 databuf.appendChar(csym.getRecordComponents().size());
850 for (VarSymbol v: csym.getRecordComponents()) {
851 //databuf.appendChar(poolWriter.putMember(v.accessor.head.snd));
852 databuf.appendChar(poolWriter.putName(v.name));
853 databuf.appendChar(poolWriter.putDescriptor(v));
854 int acountIdx = beginAttrs();
855 int acount = 0;
856 acount += writeMemberAttrs(v, true);
857 endAttrs(acountIdx, acount);
858 }
859 endAttr(alenIdx);
860 return 1;
861 }
862
863 /**
864 * Write NestMembers attribute (if needed)
865 */
939 //write static args array
940 for (LoadableConstant arg : uniqueArgs) {
941 databuf.appendChar(poolWriter.putConstant(arg));
942 }
943 }
944 endAttr(alenIdx);
945 }
946
947 /** Write field symbol, entering all references into constant pool.
948 */
949 void writeField(VarSymbol v) {
950 int flags = adjustFlags(v.flags());
951 databuf.appendChar(flags);
952 if (dumpFieldModifiers) {
953 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
954 pw.println("FIELD " + v.name);
955 pw.println("---" + flagNames(v.flags()));
956 }
957 databuf.appendChar(poolWriter.putName(v.name));
958 databuf.appendChar(poolWriter.putDescriptor(v));
959 int acountIdx = beginAttrs();
960 int acount = 0;
961 if (v.getConstValue() != null) {
962 int alenIdx = writeAttr(names.ConstantValue);
963 databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
964 endAttr(alenIdx);
965 acount++;
966 }
967 acount += writeMemberAttrs(v, false);
968 acount += writeExtraAttributes(v);
969 endAttrs(acountIdx, acount);
970 }
971
972 /** Write method symbol, entering all references into constant pool.
973 */
974 void writeMethod(MethodSymbol m) {
975 int flags = adjustFlags(m.flags());
976 databuf.appendChar(flags);
977 if (dumpMethodModifiers) {
978 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
979 pw.println("METHOD " + m.name);
980 pw.println("---" + flagNames(m.flags()));
981 }
982 databuf.appendChar(poolWriter.putName(m.name));
983 databuf.appendChar(poolWriter.putDescriptor(m));
984 int acountIdx = beginAttrs();
985 int acount = 0;
986 if (m.code != null) {
987 int alenIdx = writeAttr(names.Code);
988 writeCode(m.code);
989 m.code = null; // to conserve space
990 endAttr(alenIdx);
991 acount++;
992 }
993 List<Type> thrown = m.erasure(types).getThrownTypes();
994 if (thrown.nonEmpty()) {
995 int alenIdx = writeAttr(names.Exceptions);
996 databuf.appendChar(thrown.length());
997 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
998 databuf.appendChar(poolWriter.putClass(l.head));
999 endAttr(alenIdx);
1000 acount++;
1001 }
1002 if (m.defaultValue != null) {
1003 int alenIdx = writeAttr(names.AnnotationDefault);
1004 m.defaultValue.accept(awriter);
1005 endAttr(alenIdx);
1006 acount++;
1007 }
1008 if (target.hasMethodParameters() && (options.isSet(PARAMETERS) || m.isConstructor() && (m.flags_field & RECORD) != 0)) {
1009 if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
1010 acount += writeMethodParametersAttr(m);
1011 }
1012 acount += writeMemberAttrs(m, false);
1013 if (!m.isLambdaMethod())
1014 acount += writeParameterAttrs(m.params);
1015 acount += writeExtraAttributes(m);
1016 endAttrs(acountIdx, acount);
1017 }
1018
1019 /** Write code attribute of method.
1020 */
1021 void writeCode(Code code) {
1022 databuf.appendChar(code.max_stack);
1023 databuf.appendChar(code.max_locals);
1024 databuf.appendInt(code.cp);
1025 databuf.appendBytes(code.code, 0, code.cp);
1026 databuf.appendChar(code.catchInfo.length());
1027 for (List<char[]> l = code.catchInfo.toList();
1028 l.nonEmpty();
1208 databuf.appendByte(1);
1209 break;
1210 case FLOAT:
1211 if (debugstackmap) System.out.print("float");
1212 databuf.appendByte(2);
1213 break;
1214 case DOUBLE:
1215 if (debugstackmap) System.out.print("double");
1216 databuf.appendByte(3);
1217 break;
1218 case LONG:
1219 if (debugstackmap) System.out.print("long");
1220 databuf.appendByte(4);
1221 break;
1222 case BOT: // null
1223 if (debugstackmap) System.out.print("null");
1224 databuf.appendByte(5);
1225 break;
1226 case CLASS:
1227 case ARRAY:
1228 case TYPEVAR:
1229 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1230 databuf.appendByte(7);
1231 databuf.appendChar(poolWriter.putClass(types.erasure(t)));
1232 break;
1233 case UNINITIALIZED_THIS:
1234 if (debugstackmap) System.out.print("uninit_this");
1235 databuf.appendByte(6);
1236 break;
1237 case UNINITIALIZED_OBJECT:
1238 { UninitializedType uninitType = (UninitializedType)t;
1239 databuf.appendByte(8);
1240 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1241 databuf.appendChar(uninitType.offset);
1242 }
1243 break;
1244 default:
1245 throw new AssertionError();
1246 }
1247 }
1519 }
1520 return outFile; // may be null if write failed
1521 }
1522
1523 /** Write class `c' to outstream `out'.
1524 */
1525 public void writeClassFile(OutputStream out, ClassSymbol c)
1526 throws IOException, PoolOverflow, StringOverflow {
1527 Assert.check((c.flags() & COMPOUND) == 0);
1528 databuf.reset();
1529 poolbuf.reset();
1530
1531 Type supertype = types.supertype(c.type);
1532 List<Type> interfaces = types.interfaces(c.type);
1533 List<Type> typarams = c.type.getTypeArguments();
1534
1535 int flags;
1536 if (c.owner.kind == MDL) {
1537 flags = ACC_MODULE;
1538 } else {
1539 flags = adjustFlags(c.flags() & ~DEFAULT);
1540 if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1541 flags = flags & ClassFlags & ~STRICTFP;
1542 if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
1543 }
1544
1545 if (dumpClassModifiers) {
1546 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1547 pw.println();
1548 pw.println("CLASSFILE " + c.getQualifiedName());
1549 pw.println("---" + flagNames(flags));
1550 }
1551 databuf.appendChar(flags);
1552
1553 if (c.owner.kind == MDL) {
1554 PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1555 databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1556 } else {
1557 databuf.appendChar(poolWriter.putClass(c));
1558 }
1559 databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1560 databuf.appendChar(interfaces.length());
1561 for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1562 databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
1563 int fieldsCount = 0;
1564 int methodsCount = 0;
1565 for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
1566 switch (sym.kind) {
1567 case VAR: fieldsCount++; break;
1568 case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
1569 break;
1570 case TYP: poolWriter.enterInner((ClassSymbol)sym); break;
1571 default : Assert.error();
1572 }
1573 }
1574
1575 if (c.trans_local != null) {
1576 for (ClassSymbol local : c.trans_local) {
1577 poolWriter.enterInner(local);
1578 }
1579 }
1580
1581 databuf.appendChar(fieldsCount);
1582 writeFields(c.members());
1583 databuf.appendChar(methodsCount);
1584 writeMethods(c.members());
1585
1586 int acountIdx = beginAttrs();
1587 int acount = 0;
1588
1589 boolean sigReq =
1590 typarams.length() != 0 || supertype.allparams().length() != 0;
1591 for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1592 sigReq = l.head.allparams().length() != 0;
1593 if (sigReq) {
1594 int alenIdx = writeAttr(names.Signature);
1595 databuf.appendChar(poolWriter.putSignature(c));
1596 endAttr(alenIdx);
1597 acount++;
1648 }
1649
1650 if (c.isRecord()) {
1651 acount += writeRecordAttribute(c);
1652 }
1653
1654 if (target.hasSealedClasses()) {
1655 acount += writePermittedSubclassesIfNeeded(c);
1656 }
1657
1658 if (!poolWriter.bootstrapMethods.isEmpty()) {
1659 writeBootstrapMethods();
1660 acount++;
1661 }
1662
1663 if (!poolWriter.innerClasses.isEmpty()) {
1664 writeInnerClasses();
1665 acount++;
1666 }
1667
1668 endAttrs(acountIdx, acount);
1669
1670 out.write(poolbuf.elems, 0, poolbuf.length);
1671
1672 poolWriter.writePool(out);
1673 poolWriter.reset(); // to save space
1674
1675 out.write(databuf.elems, 0, databuf.length);
1676 }
1677
1678 /**Allows subclasses to write additional class attributes
1679 *
1680 * @return the number of attributes written
1681 */
1682 protected int writeExtraClassAttributes(ClassSymbol c) {
1683 return 0;
1684 }
1685
1686 /**Allows friends to write additional attributes
1687 *
1691 int i = 0;
1692 for (ToIntFunction<Symbol> hook : extraAttributeHooks) {
1693 i += hook.applyAsInt(sym);
1694 }
1695 return i;
1696 }
1697
1698 int adjustFlags(final long flags) {
1699 int result = (int)flags;
1700
1701 // Elide strictfp bit in class files
1702 if (target.obsoleteAccStrict())
1703 result &= ~STRICTFP;
1704
1705 if ((flags & BRIDGE) != 0)
1706 result |= ACC_BRIDGE;
1707 if ((flags & VARARGS) != 0)
1708 result |= ACC_VARARGS;
1709 if ((flags & DEFAULT) != 0)
1710 result &= ~ABSTRACT;
1711 return result;
1712 }
1713
1714 long getLastModified(FileObject filename) {
1715 long mod = 0;
1716 try {
1717 mod = filename.getLastModified();
1718 } catch (SecurityException e) {
1719 throw new AssertionError("CRT: couldn't get source file modification date: " + e.getMessage());
1720 }
1721 return mod;
1722 }
1723 }
|
23 * questions.
24 */
25
26 package com.sun.tools.javac.jvm;
27
28 import java.io.*;
29 import java.util.LinkedHashMap;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.LinkedHashSet;
33 import java.util.function.ToIntFunction;
34
35 import javax.tools.JavaFileManager;
36 import javax.tools.FileObject;
37 import javax.tools.JavaFileManager.Location;
38 import javax.tools.JavaFileObject;
39
40 import com.sun.tools.javac.code.*;
41 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
42 import com.sun.tools.javac.code.Directive.*;
43 import com.sun.tools.javac.code.Scope.WriteableScope;
44 import com.sun.tools.javac.code.Source.Feature;
45 import com.sun.tools.javac.code.Symbol.*;
46 import com.sun.tools.javac.code.Type.*;
47 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
48 import com.sun.tools.javac.comp.Check;
49 import com.sun.tools.javac.file.PathFileObject;
50 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
51 import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
52 import com.sun.tools.javac.resources.CompilerProperties.Errors;
53 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
54 import com.sun.tools.javac.util.*;
55 import com.sun.tools.javac.util.List;
56
57 import static com.sun.tools.javac.code.Flags.*;
58 import static com.sun.tools.javac.code.Kinds.Kind.*;
59 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
60 import static com.sun.tools.javac.code.TypeTag.*;
61 import static com.sun.tools.javac.main.Option.*;
62
63 import static javax.tools.StandardLocation.CLASS_OUTPUT;
126
127 /** An output buffer for member info.
128 */
129 public ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
130
131 /** An output buffer for the constant pool.
132 */
133 ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
134
135 /** The constant pool writer.
136 */
137 final PoolWriter poolWriter;
138
139 /** The log to use for verbose output.
140 */
141 private final Log log;
142
143 /** The name table. */
144 private final Names names;
145
146 private final Symtab syms;
147
148 /** Access to files. */
149 private final JavaFileManager fileManager;
150
151 /** The tags and constants used in compressed stackmap. */
152 static final int SAME_FRAME_SIZE = 64;
153 static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
154 static final int SAME_FRAME_EXTENDED = 251;
155 static final int FULL_FRAME = 255;
156 static final int MAX_LOCAL_LENGTH_DIFF = 4;
157
158 /** Get the ClassWriter instance for this context. */
159 public static ClassWriter instance(Context context) {
160 ClassWriter instance = context.get(classWriterKey);
161 if (instance == null)
162 instance = new ClassWriter(context);
163 return instance;
164 }
165
166 /** Construct a class writer, given an options table.
167 */
168 protected ClassWriter(Context context) {
169 context.put(classWriterKey, this);
170
171 log = Log.instance(context);
172 names = Names.instance(context);
173 options = Options.instance(context);
174 preview = Preview.instance(context);
175 target = Target.instance(context);
176 source = Source.instance(context);
177 types = Types.instance(context);
178 check = Check.instance(context);
179 fileManager = context.get(JavaFileManager.class);
180 poolWriter = Gen.instance(context).poolWriter;
181 syms = Symtab.instance(context);
182
183 verbose = options.isSet(VERBOSE);
184 genCrt = options.isSet(XJCOV);
185 debugstackmap = options.isSet("debug.stackmap");
186
187 emitSourceFile = options.isUnset(G_CUSTOM) ||
188 options.isSet(G_CUSTOM, "source");
189
190 String modifierFlags = options.get("debug.dumpmodifiers");
191 if (modifierFlags != null) {
192 dumpClassModifiers = modifierFlags.indexOf('c') != -1;
193 dumpFieldModifiers = modifierFlags.indexOf('f') != -1;
194 dumpInnerClassModifiers = modifierFlags.indexOf('i') != -1;
195 dumpMethodModifiers = modifierFlags.indexOf('m') != -1;
196 }
197 }
198
199 public void addExtraAttributes(ToIntFunction<Symbol> addExtraAttributes) {
200 extraAttributeHooks = extraAttributeHooks.prepend(addExtraAttributes);
201 }
202
203 /******************************************************************
204 * Diagnostics: dump generated class names and modifiers
205 ******************************************************************/
206
207 /** Value of option 'dumpmodifiers' is a string
208 * indicating which modifiers should be dumped for debugging:
209 * 'c' -- classes
210 * 'f' -- fields
211 * 'i' -- innerclass attributes
212 * 'm' -- methods
213 * For example, to dump everything:
214 * javac -XDdumpmodifiers=cifm MyProg.java
215 */
216 private boolean dumpClassModifiers; // -XDdumpmodifiers=c
217 private boolean dumpFieldModifiers; // -XDdumpmodifiers=f
218 private boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i
219 private boolean dumpMethodModifiers; // -XDdumpmodifiers=m
220
221 /** Return flags as a string, separated by " ".
222 */
223 public static String flagNames(long flags) {
224 StringBuilder sbuf = new StringBuilder();
225 int i = 0;
226 long f = flags & StandardFlags;
227 while (f != 0) {
228 if ((f & 1) != 0) {
229 sbuf.append(" ");
230 sbuf.append(flagName[i]);
231 }
232 f = f >> 1;
233 i++;
234 }
235 return sbuf.toString();
236 }
237 //where
238 private static final String[] flagName = {
239 "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL",
240 "IDENTITY", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE",
241 "ABSTRACT", "STRICTFP"};
242
243 /******************************************************************
244 * Output routines
245 ******************************************************************/
246
247 /** Write a character into given byte buffer;
248 * byte buffer will not be grown.
249 */
250 void putChar(ByteBuffer buf, int op, int x) {
251 buf.elems[op ] = (byte)((x >> 8) & 0xFF);
252 buf.elems[op+1] = (byte)((x ) & 0xFF);
253 }
254
255 /** Write an integer into given byte buffer;
256 * byte buffer will not be grown.
257 */
258 void putInt(ByteBuffer buf, int adr, int x) {
259 buf.elems[adr ] = (byte)((x >> 24) & 0xFF);
260 buf.elems[adr+1] = (byte)((x >> 16) & 0xFF);
811 databuf.appendChar(poolWriter.putClass(srvc));
812 databuf.appendChar(impls.size());
813 impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
814 });
815
816 endAttr(alenIdx);
817 return 1;
818 }
819
820 /**********************************************************************
821 * Writing Objects
822 **********************************************************************/
823
824 /** Write "inner classes" attribute.
825 */
826 void writeInnerClasses() {
827 int alenIdx = writeAttr(names.InnerClasses);
828 databuf.appendChar(poolWriter.innerClasses.size());
829 for (ClassSymbol inner : poolWriter.innerClasses) {
830 inner.markAbstractIfNeeded(types);
831 char flags = (char) adjustFlags(inner.flags_field & ~STRICTFP); // inner classes should not have the strictfp flag set.
832 if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
833 if (dumpInnerClassModifiers) {
834 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
835 pw.println("INNERCLASS " + inner.name);
836 pw.println("---" + flagNames(flags));
837 }
838 databuf.appendChar(poolWriter.putClass(inner));
839 databuf.appendChar(
840 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
841 databuf.appendChar(
842 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
843 databuf.appendChar(flags);
844 }
845 endAttr(alenIdx);
846 }
847
848 /** Write out "Preload" attribute by enumerating the value classes encountered in field/method descriptors during this compilation.
849 */
850 void writePreloadAttribute() {
851 int alenIdx = writeAttr(names.Preload);
852 databuf.appendChar(poolWriter.preloadClasses.size());
853 for (ClassSymbol c : poolWriter.preloadClasses) {
854 databuf.appendChar(poolWriter.putClass(c));
855 }
856 endAttr(alenIdx);
857 }
858
859 int writeRecordAttribute(ClassSymbol csym) {
860 int alenIdx = writeAttr(names.Record);
861 Scope s = csym.members();
862 databuf.appendChar(csym.getRecordComponents().size());
863 for (VarSymbol v: csym.getRecordComponents()) {
864 //databuf.appendChar(poolWriter.putMember(v.accessor.head.snd));
865 databuf.appendChar(poolWriter.putName(v.name));
866 databuf.appendChar(poolWriter.putDescriptor(v));
867 int acountIdx = beginAttrs();
868 int acount = 0;
869 acount += writeMemberAttrs(v, true);
870 endAttrs(acountIdx, acount);
871 }
872 endAttr(alenIdx);
873 return 1;
874 }
875
876 /**
877 * Write NestMembers attribute (if needed)
878 */
952 //write static args array
953 for (LoadableConstant arg : uniqueArgs) {
954 databuf.appendChar(poolWriter.putConstant(arg));
955 }
956 }
957 endAttr(alenIdx);
958 }
959
960 /** Write field symbol, entering all references into constant pool.
961 */
962 void writeField(VarSymbol v) {
963 int flags = adjustFlags(v.flags());
964 databuf.appendChar(flags);
965 if (dumpFieldModifiers) {
966 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
967 pw.println("FIELD " + v.name);
968 pw.println("---" + flagNames(v.flags()));
969 }
970 databuf.appendChar(poolWriter.putName(v.name));
971 databuf.appendChar(poolWriter.putDescriptor(v));
972 Type fldType = v.erasure(types);
973 if (fldType.requiresPreload(v.owner)) {
974 poolWriter.enterPreloadClass((ClassSymbol) fldType.tsym);
975 }
976 int acountIdx = beginAttrs();
977 int acount = 0;
978 if (v.getConstValue() != null) {
979 int alenIdx = writeAttr(names.ConstantValue);
980 databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
981 endAttr(alenIdx);
982 acount++;
983 }
984 acount += writeMemberAttrs(v, false);
985 acount += writeExtraAttributes(v);
986 endAttrs(acountIdx, acount);
987 }
988
989 /** Write method symbol, entering all references into constant pool.
990 */
991 void writeMethod(MethodSymbol m) {
992 int flags = adjustFlags(m.flags());
993 databuf.appendChar(flags);
994 if (dumpMethodModifiers) {
995 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
996 pw.println("METHOD " + m.name);
997 pw.println("---" + flagNames(m.flags()));
998 }
999 databuf.appendChar(poolWriter.putName(m.name));
1000 databuf.appendChar(poolWriter.putDescriptor(m));
1001 MethodType mtype = (MethodType) m.externalType(types);
1002 for (Type t : mtype.getParameterTypes()) {
1003 if (t.requiresPreload(m.owner)) {
1004 poolWriter.enterPreloadClass((ClassSymbol) t.tsym);
1005 }
1006 }
1007 Type returnType = mtype.getReturnType();
1008 if (returnType.requiresPreload(m.owner)) {
1009 poolWriter.enterPreloadClass((ClassSymbol) returnType.tsym);
1010 }
1011 int acountIdx = beginAttrs();
1012 int acount = 0;
1013 if (m.code != null) {
1014 int alenIdx = writeAttr(names.Code);
1015 writeCode(m.code);
1016 m.code = null; // to conserve space
1017 endAttr(alenIdx);
1018 acount++;
1019 }
1020 List<Type> thrown = m.erasure(types).getThrownTypes();
1021 if (thrown.nonEmpty()) {
1022 int alenIdx = writeAttr(names.Exceptions);
1023 databuf.appendChar(thrown.length());
1024 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1025 databuf.appendChar(poolWriter.putClass(l.head));
1026 endAttr(alenIdx);
1027 acount++;
1028 }
1029 if (m.defaultValue != null) {
1030 int alenIdx = writeAttr(names.AnnotationDefault);
1031 m.defaultValue.accept(awriter);
1032 endAttr(alenIdx);
1033 acount++;
1034 }
1035 if (target.hasMethodParameters() && (
1036 options.isSet(PARAMETERS)
1037 || ((m.flags_field & RECORD) != 0 && (m.isConstructor() || m.isValueObjectFactory())))) {
1038 if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
1039 acount += writeMethodParametersAttr(m);
1040 }
1041 acount += writeMemberAttrs(m, false);
1042 if (!m.isLambdaMethod())
1043 acount += writeParameterAttrs(m.params);
1044 acount += writeExtraAttributes(m);
1045 endAttrs(acountIdx, acount);
1046 }
1047
1048 /** Write code attribute of method.
1049 */
1050 void writeCode(Code code) {
1051 databuf.appendChar(code.max_stack);
1052 databuf.appendChar(code.max_locals);
1053 databuf.appendInt(code.cp);
1054 databuf.appendBytes(code.code, 0, code.cp);
1055 databuf.appendChar(code.catchInfo.length());
1056 for (List<char[]> l = code.catchInfo.toList();
1057 l.nonEmpty();
1237 databuf.appendByte(1);
1238 break;
1239 case FLOAT:
1240 if (debugstackmap) System.out.print("float");
1241 databuf.appendByte(2);
1242 break;
1243 case DOUBLE:
1244 if (debugstackmap) System.out.print("double");
1245 databuf.appendByte(3);
1246 break;
1247 case LONG:
1248 if (debugstackmap) System.out.print("long");
1249 databuf.appendByte(4);
1250 break;
1251 case BOT: // null
1252 if (debugstackmap) System.out.print("null");
1253 databuf.appendByte(5);
1254 break;
1255 case CLASS:
1256 case ARRAY:
1257 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1258 databuf.appendByte(7);
1259 databuf.appendChar(t.isPrimitiveClass() ? poolWriter.putClass(new ConstantPoolQType(types.erasure(t), types)) : poolWriter.putClass(types.erasure(t)));
1260 break;
1261 case TYPEVAR:
1262 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1263 databuf.appendByte(7);
1264 databuf.appendChar(poolWriter.putClass(types.erasure(t)));
1265 break;
1266 case UNINITIALIZED_THIS:
1267 if (debugstackmap) System.out.print("uninit_this");
1268 databuf.appendByte(6);
1269 break;
1270 case UNINITIALIZED_OBJECT:
1271 { UninitializedType uninitType = (UninitializedType)t;
1272 databuf.appendByte(8);
1273 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1274 databuf.appendChar(uninitType.offset);
1275 }
1276 break;
1277 default:
1278 throw new AssertionError();
1279 }
1280 }
1552 }
1553 return outFile; // may be null if write failed
1554 }
1555
1556 /** Write class `c' to outstream `out'.
1557 */
1558 public void writeClassFile(OutputStream out, ClassSymbol c)
1559 throws IOException, PoolOverflow, StringOverflow {
1560 Assert.check((c.flags() & COMPOUND) == 0);
1561 databuf.reset();
1562 poolbuf.reset();
1563
1564 Type supertype = types.supertype(c.type);
1565 List<Type> interfaces = types.interfaces(c.type);
1566 List<Type> typarams = c.type.getTypeArguments();
1567
1568 int flags;
1569 if (c.owner.kind == MDL) {
1570 flags = ACC_MODULE;
1571 } else {
1572 flags = adjustFlags(c.flags() & ~(DEFAULT | STRICTFP));
1573 if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1574 flags = flags & AdjustedClassFlags;
1575 }
1576
1577 if (dumpClassModifiers) {
1578 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1579 pw.println();
1580 pw.println("CLASSFILE " + c.getQualifiedName());
1581 pw.println("---" + flagNames(flags));
1582 }
1583 databuf.appendChar(flags);
1584
1585 if (c.owner.kind == MDL) {
1586 PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1587 databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1588 } else {
1589 databuf.appendChar(poolWriter.putClass(c));
1590 }
1591 databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1592 databuf.appendChar(interfaces.length());
1593 for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1594 databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
1595 int fieldsCount = 0;
1596 int methodsCount = 0;
1597 for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
1598 switch (sym.kind) {
1599 case VAR: fieldsCount++; break;
1600 case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
1601 break;
1602 case TYP: poolWriter.enterInnerClass((ClassSymbol)sym); break;
1603 default : Assert.error();
1604 }
1605 }
1606
1607 if (c.trans_local != null) {
1608 for (ClassSymbol local : c.trans_local) {
1609 poolWriter.enterInnerClass(local);
1610 }
1611 }
1612
1613 databuf.appendChar(fieldsCount);
1614 writeFields(c.members());
1615 databuf.appendChar(methodsCount);
1616 writeMethods(c.members());
1617
1618 int acountIdx = beginAttrs();
1619 int acount = 0;
1620
1621 boolean sigReq =
1622 typarams.length() != 0 || supertype.allparams().length() != 0;
1623 for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1624 sigReq = l.head.allparams().length() != 0;
1625 if (sigReq) {
1626 int alenIdx = writeAttr(names.Signature);
1627 databuf.appendChar(poolWriter.putSignature(c));
1628 endAttr(alenIdx);
1629 acount++;
1680 }
1681
1682 if (c.isRecord()) {
1683 acount += writeRecordAttribute(c);
1684 }
1685
1686 if (target.hasSealedClasses()) {
1687 acount += writePermittedSubclassesIfNeeded(c);
1688 }
1689
1690 if (!poolWriter.bootstrapMethods.isEmpty()) {
1691 writeBootstrapMethods();
1692 acount++;
1693 }
1694
1695 if (!poolWriter.innerClasses.isEmpty()) {
1696 writeInnerClasses();
1697 acount++;
1698 }
1699
1700 if (!poolWriter.preloadClasses.isEmpty()) {
1701 writePreloadAttribute();
1702 acount++;
1703 }
1704
1705 endAttrs(acountIdx, acount);
1706
1707 out.write(poolbuf.elems, 0, poolbuf.length);
1708
1709 poolWriter.writePool(out);
1710 poolWriter.reset(); // to save space
1711
1712 out.write(databuf.elems, 0, databuf.length);
1713 }
1714
1715 /**Allows subclasses to write additional class attributes
1716 *
1717 * @return the number of attributes written
1718 */
1719 protected int writeExtraClassAttributes(ClassSymbol c) {
1720 return 0;
1721 }
1722
1723 /**Allows friends to write additional attributes
1724 *
1728 int i = 0;
1729 for (ToIntFunction<Symbol> hook : extraAttributeHooks) {
1730 i += hook.applyAsInt(sym);
1731 }
1732 return i;
1733 }
1734
1735 int adjustFlags(final long flags) {
1736 int result = (int)flags;
1737
1738 // Elide strictfp bit in class files
1739 if (target.obsoleteAccStrict())
1740 result &= ~STRICTFP;
1741
1742 if ((flags & BRIDGE) != 0)
1743 result |= ACC_BRIDGE;
1744 if ((flags & VARARGS) != 0)
1745 result |= ACC_VARARGS;
1746 if ((flags & DEFAULT) != 0)
1747 result &= ~ABSTRACT;
1748 if ((flags & PRIMITIVE_CLASS) != 0)
1749 result |= ACC_PRIMITIVE;
1750 if ((flags & VALUE_CLASS) != 0)
1751 result |= ACC_VALUE;
1752 if ((flags & IDENTITY_TYPE) != 0)
1753 result |= ACC_IDENTITY;
1754 return result;
1755 }
1756
1757 long getLastModified(FileObject filename) {
1758 long mod = 0;
1759 try {
1760 mod = filename.getLastModified();
1761 } catch (SecurityException e) {
1762 throw new AssertionError("CRT: couldn't get source file modification date: " + e.getMessage());
1763 }
1764 return mod;
1765 }
1766 }
|