< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java

Print this page

   1 /*
   2  * Copyright (c) 1999, 2024, 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

 129     /** An output buffer for the constant pool.
 130      */
 131     ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
 132 
 133     /** The constant pool writer.
 134      */
 135     final PoolWriter poolWriter;
 136 
 137     /** The log to use for verbose output.
 138      */
 139     private final Log log;
 140 
 141     /** The name table. */
 142     private final Names names;
 143 
 144     /** Access to files. */
 145     private final JavaFileManager fileManager;
 146 
 147     /** The tags and constants used in compressed stackmap. */
 148     static final int SAME_FRAME_SIZE = 64;

 149     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 150     static final int SAME_FRAME_EXTENDED = 251;
 151     static final int FULL_FRAME = 255;
 152     static final int MAX_LOCAL_LENGTH_DIFF = 4;
 153 
 154     /** Get the ClassWriter instance for this context. */
 155     public static ClassWriter instance(Context context) {
 156         ClassWriter instance = context.get(classWriterKey);
 157         if (instance == null)
 158             instance = new ClassWriter(context);
 159         return instance;
 160     }
 161 
 162     /** Construct a class writer, given an options table.
 163      */
 164     @SuppressWarnings("this-escape")
 165     protected ClassWriter(Context context) {
 166         context.put(classWriterKey, this);
 167 
 168         log = Log.instance(context);

 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);

 820         for (ProvidesDirective p : m.provides) {
 821             mergedProvides.computeIfAbsent(p.service, s -> new LinkedHashSet<>()).addAll(p.impls);
 822         }
 823         databuf.appendChar(mergedProvides.size());
 824         mergedProvides.forEach((srvc, impls) -> {
 825             databuf.appendChar(poolWriter.putClass(srvc));
 826             databuf.appendChar(impls.size());
 827             impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
 828         });
 829 
 830         endAttr(alenIdx);
 831         return 1;
 832     }
 833 
 834 /* ********************************************************************
 835  * Writing Objects
 836  **********************************************************************/
 837 
 838     /** Write "inner classes" attribute.
 839      */
 840     void writeInnerClasses() {
 841         int alenIdx = writeAttr(names.InnerClasses);
 842         databuf.appendChar(poolWriter.innerClasses.size());
 843         for (ClassSymbol inner : poolWriter.innerClasses) {
 844             inner.markAbstractIfNeeded(types);
 845             int flags = adjustFlags(inner.flags_field);
 846             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
 847             flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.




 848             if (dumpInnerClassModifiers) {
 849                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 850                 pw.println("INNERCLASS  " + inner.name);
 851                 pw.println("---" + flagNames(flags));
 852             }
 853             databuf.appendChar(poolWriter.putClass(inner));
 854             databuf.appendChar(
 855                 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
 856             databuf.appendChar(
 857                 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
 858             databuf.appendChar(flags);
 859         }
 860         endAttr(alenIdx);
 861     }
 862 











 863     int writeRecordAttribute(ClassSymbol csym) {
 864         int alenIdx = writeAttr(names.Record);
 865         Scope s = csym.members();
 866         databuf.appendChar(csym.getRecordComponents().size());
 867         for (VarSymbol v: csym.getRecordComponents()) {
 868             //databuf.appendChar(poolWriter.putMember(v.accessor.head.snd));
 869             databuf.appendChar(poolWriter.putName(v.name));
 870             databuf.appendChar(poolWriter.putDescriptor(v));
 871             int acountIdx = beginAttrs();
 872             int acount = 0;
 873             acount += writeMemberAttrs(v, true);
 874             endAttrs(acountIdx, acount);
 875         }
 876         endAttr(alenIdx);
 877         return 1;
 878     }
 879 
 880     /**
 881      * Write NestMembers attribute (if needed)
 882      */

 956             }
 957         } while (lastBootstrapMethods < poolWriter.bootstrapMethods.size());
 958         databuf.appendChar(poolWriter.bootstrapMethods.size());
 959         for (BsmKey bsmKey : poolWriter.bootstrapMethods.keySet()) {
 960             //write BSM handle
 961             databuf.appendChar(poolWriter.putConstant(bsmKey.bsm));
 962             LoadableConstant[] uniqueArgs = bsmKey.staticArgs;
 963             //write static args length
 964             databuf.appendChar(uniqueArgs.length);
 965             //write static args array
 966             for (LoadableConstant arg : uniqueArgs) {
 967                 databuf.appendChar(poolWriter.putConstant(arg));
 968             }
 969         }
 970         endAttr(alenIdx);
 971     }
 972 
 973     /** Write field symbol, entering all references into constant pool.
 974      */
 975     void writeField(VarSymbol v) {
 976         int flags = adjustFlags(v.flags());
 977         databuf.appendChar(flags);
 978         if (dumpFieldModifiers) {
 979             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 980             pw.println("FIELD  " + v.name);
 981             pw.println("---" + flagNames(v.flags()));
 982         }
 983         databuf.appendChar(poolWriter.putName(v.name));
 984         databuf.appendChar(poolWriter.putDescriptor(v));







 985         int acountIdx = beginAttrs();
 986         int acount = 0;
 987         if (v.getConstValue() != null) {
 988             int alenIdx = writeAttr(names.ConstantValue);
 989             databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
 990             endAttr(alenIdx);
 991             acount++;
 992         }
 993         acount += writeMemberAttrs(v, false);
 994         acount += writeExtraAttributes(v);
 995         endAttrs(acountIdx, acount);
 996     }
 997 
 998     /** Write method symbol, entering all references into constant pool.
 999      */
1000     void writeMethod(MethodSymbol m) {
1001         int flags = adjustFlags(m.flags());
1002         databuf.appendChar(flags);
1003         if (dumpMethodModifiers) {
1004             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1005             pw.println("METHOD  " + m.name);
1006             pw.println("---" + flagNames(m.flags()));
1007         }
1008         databuf.appendChar(poolWriter.putName(m.name));
1009         databuf.appendChar(poolWriter.putDescriptor(m));
















1010         int acountIdx = beginAttrs();
1011         int acount = 0;
1012         if (m.code != null) {
1013             int alenIdx = writeAttr(names.Code);
1014             writeCode(m.code);
1015             m.code = null; // to conserve space
1016             endAttr(alenIdx);
1017             acount++;
1018         }
1019         List<Type> thrown = m.erasure(types).getThrownTypes();
1020         if (thrown.nonEmpty()) {
1021             int alenIdx = writeAttr(names.Exceptions);
1022             databuf.appendChar(thrown.length());
1023             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1024                 databuf.appendChar(poolWriter.putClass(l.head));
1025             endAttr(alenIdx);
1026             acount++;
1027         }
1028         if (m.defaultValue != null) {
1029             int alenIdx = writeAttr(names.AnnotationDefault);

1280                 break;
1281             case UNINITIALIZED_THIS:
1282                 if (debugstackmap) System.out.print("uninit_this");
1283                 databuf.appendByte(6);
1284                 break;
1285             case UNINITIALIZED_OBJECT:
1286                 { UninitializedType uninitType = (UninitializedType)t;
1287                 databuf.appendByte(8);
1288                 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1289                 databuf.appendChar(uninitType.offset);
1290                 }
1291                 break;
1292             default:
1293                 throw new AssertionError();
1294             }
1295         }
1296 
1297     /** An entry in the JSR202 StackMapTable */
1298     abstract static class StackMapTableFrame {
1299         abstract int getFrameType();





1300 
1301         void write(ClassWriter writer) {
1302             int frameType = getFrameType();
1303             writer.databuf.appendByte(frameType);
1304             if (writer.debugstackmap) System.out.print(" frame_type=" + frameType);
1305         }
1306 
1307         static class SameFrame extends StackMapTableFrame {
1308             final int offsetDelta;
1309             SameFrame(int offsetDelta) {

1310                 this.offsetDelta = offsetDelta;
1311             }
1312             int getFrameType() {
1313                 return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta : SAME_FRAME_EXTENDED;
1314             }
1315             @Override
1316             void write(ClassWriter writer) {
1317                 super.write(writer);
1318                 if (getFrameType() == SAME_FRAME_EXTENDED) {
1319                     writer.databuf.appendChar(offsetDelta);
1320                     if (writer.debugstackmap){
1321                         System.out.print(" offset_delta=" + offsetDelta);
1322                     }
1323                 }
1324             }
1325         }
1326 
1327         static class SameLocals1StackItemFrame extends StackMapTableFrame {
1328             final int offsetDelta;
1329             final Type stack;
1330             SameLocals1StackItemFrame(int offsetDelta, Type stack) {

1331                 this.offsetDelta = offsetDelta;
1332                 this.stack = stack;
1333             }
1334             int getFrameType() {
1335                 return (offsetDelta < SAME_FRAME_SIZE) ?
1336                        (SAME_FRAME_SIZE + offsetDelta) :
1337                        SAME_LOCALS_1_STACK_ITEM_EXTENDED;
1338             }
1339             @Override
1340             void write(ClassWriter writer) {
1341                 super.write(writer);
1342                 if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
1343                     writer.databuf.appendChar(offsetDelta);
1344                     if (writer.debugstackmap) {
1345                         System.out.print(" offset_delta=" + offsetDelta);
1346                     }
1347                 }
1348                 if (writer.debugstackmap) {
1349                     System.out.print(" stack[" + 0 + "]=");
1350                 }
1351                 writer.writeStackMapType(stack);
1352             }
1353         }
1354 
1355         static class ChopFrame extends StackMapTableFrame {
1356             final int frameType;
1357             final int offsetDelta;
1358             ChopFrame(int frameType, int offsetDelta) {

1359                 this.frameType = frameType;
1360                 this.offsetDelta = offsetDelta;
1361             }
1362             int getFrameType() { return frameType; }
1363             @Override
1364             void write(ClassWriter writer) {
1365                 super.write(writer);
1366                 writer.databuf.appendChar(offsetDelta);
1367                 if (writer.debugstackmap) {
1368                     System.out.print(" offset_delta=" + offsetDelta);
1369                 }
1370             }
1371         }
1372 
1373         static class AppendFrame extends StackMapTableFrame {
1374             final int frameType;
1375             final int offsetDelta;
1376             final Type[] locals;
1377             AppendFrame(int frameType, int offsetDelta, Type[] locals) {

1378                 this.frameType = frameType;
1379                 this.offsetDelta = offsetDelta;
1380                 this.locals = locals;
1381             }
1382             int getFrameType() { return frameType; }
1383             @Override
1384             void write(ClassWriter writer) {
1385                 super.write(writer);
1386                 writer.databuf.appendChar(offsetDelta);
1387                 if (writer.debugstackmap) {
1388                     System.out.print(" offset_delta=" + offsetDelta);
1389                 }
1390                 for (int i=0; i<locals.length; i++) {
1391                      if (writer.debugstackmap) System.out.print(" locals[" + i + "]=");
1392                      writer.writeStackMapType(locals[i]);
1393                 }
1394             }
1395         }
1396 
1397         static class FullFrame extends StackMapTableFrame {
1398             final int offsetDelta;
1399             final Type[] locals;
1400             final Type[] stack;
1401             FullFrame(int offsetDelta, Type[] locals, Type[] stack) {

1402                 this.offsetDelta = offsetDelta;
1403                 this.locals = locals;
1404                 this.stack = stack;
1405             }
1406             int getFrameType() { return FULL_FRAME; }
1407             @Override
1408             void write(ClassWriter writer) {
1409                 super.write(writer);
1410                 writer.databuf.appendChar(offsetDelta);
1411                 writer.databuf.appendChar(locals.length);
1412                 if (writer.debugstackmap) {
1413                     System.out.print(" offset_delta=" + offsetDelta);
1414                     System.out.print(" nlocals=" + locals.length);
1415                 }
1416                 for (int i=0; i<locals.length; i++) {
1417                     if (writer.debugstackmap) System.out.print(" locals[" + i + "]=");
1418                     writer.writeStackMapType(locals[i]);
1419                 }
1420 
1421                 writer.databuf.appendChar(stack.length);
1422                 if (writer.debugstackmap) { System.out.print(" nstack=" + stack.length); }
1423                 for (int i=0; i<stack.length; i++) {
1424                     if (writer.debugstackmap) System.out.print(" stack[" + i + "]=");
1425                     writer.writeStackMapType(stack[i]);
1426                 }
1427             }
1428         }
1429 































1430        /** Compare this frame with the previous frame and produce
1431         *  an entry of compressed stack map frame. */
1432         static StackMapTableFrame getInstance(Code.StackMapFrame this_frame,
1433                                               int prev_pc,
1434                                               Type[] prev_locals,
1435                                               Types types) {
1436             Type[] locals = this_frame.locals;
1437             Type[] stack = this_frame.stack;
1438             int offset_delta = this_frame.pc - prev_pc - 1;
1439             if (stack.length == 1) {
1440                 if (locals.length == prev_locals.length
1441                     && compare(prev_locals, locals, types) == 0) {
1442                     return new SameLocals1StackItemFrame(offset_delta, stack[0]);
1443                 }
1444             } else if (stack.length == 0) {
1445                 int diff_length = compare(prev_locals, locals, types);
1446                 if (diff_length == 0) {
1447                     return new SameFrame(offset_delta);
1448                 } else if (-MAX_LOCAL_LENGTH_DIFF < diff_length && diff_length < 0) {
1449                     // APPEND
1450                     Type[] local_diff = new Type[-diff_length];
1451                     for (int i=prev_locals.length, j=0; i<locals.length; i++,j++) {
1452                         local_diff[j] = locals[i];
1453                     }
1454                     return new AppendFrame(SAME_FRAME_EXTENDED - diff_length,
1455                                            offset_delta,
1456                                            local_diff);
1457                 } else if (0 < diff_length && diff_length < MAX_LOCAL_LENGTH_DIFF) {
1458                     // CHOP
1459                     return new ChopFrame(SAME_FRAME_EXTENDED - diff_length,
1460                                          offset_delta);
1461                 }
1462             }
1463             // FULL_FRAME
1464             return new FullFrame(offset_delta, locals, stack);
1465         }
1466 
1467         static boolean isInt(Type t) {
1468             return (t.getTag().isStrictSubRangeOf(INT)  || t.hasTag(BOOLEAN));
1469         }
1470 
1471         static boolean isSameType(Type t1, Type t2, Types types) {
1472             if (t1 == null) { return t2 == null; }
1473             if (t2 == null) { return false; }
1474 
1475             if (isInt(t1) && isInt(t2)) { return true; }
1476 
1477             if (t1.hasTag(UNINITIALIZED_THIS)) {
1478                 return t2.hasTag(UNINITIALIZED_THIS);
1479             } else if (t1.hasTag(UNINITIALIZED_OBJECT)) {
1480                 if (t2.hasTag(UNINITIALIZED_OBJECT)) {
1481                     return ((UninitializedType)t1).offset == ((UninitializedType)t2).offset;
1482                 } else {
1483                     return false;
1484                 }

1567         }
1568         return outFile; // may be null if write failed
1569     }
1570 
1571     /** Write class `c' to outstream `out'.
1572      */
1573     public void writeClassFile(OutputStream out, ClassSymbol c)
1574         throws IOException, PoolOverflow, StringOverflow {
1575         Assert.check((c.flags() & COMPOUND) == 0);
1576         databuf.reset();
1577         poolbuf.reset();
1578 
1579         Type supertype = types.supertype(c.type);
1580         List<Type> interfaces = types.interfaces(c.type);
1581         List<Type> typarams = c.type.getTypeArguments();
1582 
1583         int flags;
1584         if (c.owner.kind == MDL) {
1585             flags = ACC_MODULE;
1586         } else {
1587             flags = adjustFlags(c.flags() & ~DEFAULT);

1588             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1589             flags = flags & ClassFlags & ~STRICTFP;
1590             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
1591         }
1592 
1593         if (dumpClassModifiers) {
1594             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1595             pw.println();
1596             pw.println("CLASSFILE  " + c.getQualifiedName());
1597             pw.println("---" + flagNames(flags));
1598         }
1599         databuf.appendChar(flags);
1600 
1601         if (c.owner.kind == MDL) {
1602             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1603             databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1604         } else {
1605             databuf.appendChar(poolWriter.putClass(c));
1606         }
1607         databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1608         databuf.appendChar(interfaces.length());
1609         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1610             databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));

1664             acount++;
1665             // Append CompilationID attribute
1666             alenIdx = writeAttr(names.CompilationID);
1667             databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(System.currentTimeMillis()))));
1668             endAttr(alenIdx);
1669             acount++;
1670         }
1671 
1672         acount += writeFlagAttrs(c.flags());
1673         acount += writeJavaAnnotations(c.getRawAttributes());
1674         acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
1675         acount += writeEnclosingMethodAttribute(c);
1676         if (c.owner.kind == MDL) {
1677             acount += writeModuleAttribute(c);
1678             acount += writeFlagAttrs(c.owner.flags() & ~DEPRECATED);
1679         }
1680         acount += writeExtraClassAttributes(c);
1681         acount += writeExtraAttributes(c);
1682 
1683         poolbuf.appendInt(JAVA_MAGIC);
1684         if (preview.isEnabled() && preview.usesPreview(c.sourcefile)) {

1685             poolbuf.appendChar(ClassFile.PREVIEW_MINOR_VERSION);
1686         } else {
1687             poolbuf.appendChar(target.minorVersion);
1688         }
1689         poolbuf.appendChar(target.majorVersion);
1690 
1691         if (c.owner.kind != MDL) {
1692             if (target.hasNestmateAccess()) {
1693                 acount += writeNestMembersIfNeeded(c);
1694                 acount += writeNestHostIfNeeded(c);
1695             }
1696         }
1697 
1698         if (c.isRecord()) {
1699             acount += writeRecordAttribute(c);
1700         }
1701 
1702         if (target.hasSealedClasses()) {
1703             acount += writePermittedSubclassesIfNeeded(c);
1704         }
1705 
1706         if (!poolWriter.bootstrapMethods.isEmpty()) {
1707             writeBootstrapMethods();
1708             acount++;
1709         }
1710 
1711         if (!poolWriter.innerClasses.isEmpty()) {
1712             writeInnerClasses();





1713             acount++;
1714         }
1715 
1716         endAttrs(acountIdx, acount);
1717 
1718         out.write(poolbuf.elems, 0, poolbuf.length);
1719 
1720         poolWriter.writePool(out);
1721         poolWriter.reset(); // to save space
1722 
1723         out.write(databuf.elems, 0, databuf.length);
1724     }
1725 
1726      /**Allows subclasses to write additional class attributes
1727       *
1728       * @return the number of attributes written
1729       */
1730     protected int writeExtraClassAttributes(ClassSymbol c) {
1731         return 0;
1732     }
1733 
1734     /**Allows friends to write additional attributes
1735      *
1736      * @return the number of attributes written
1737      */
1738     protected int writeExtraAttributes(Symbol sym) {
1739         int i = 0;
1740         for (ToIntFunction<Symbol> hook : extraAttributeHooks) {
1741             i += hook.applyAsInt(sym);
1742         }
1743         return i;
1744     }
1745 
1746     int adjustFlags(final long flags) {
1747         int result = (int)flags;
1748 
1749         // Elide strictfp bit in class files
1750         if (target.obsoleteAccStrict())
1751             result &= ~STRICTFP;
1752 
1753         if ((flags & BRIDGE) != 0)
1754             result |= ACC_BRIDGE;
1755         if ((flags & VARARGS) != 0)
1756             result |= ACC_VARARGS;
1757         if ((flags & DEFAULT) != 0)
1758             result &= ~ABSTRACT;








1759         return result;
1760     }
1761 
1762     long getLastModified(FileObject filename) {
1763         return filename.getLastModified();
1764     }
1765 }

   1 /*
   2  * Copyright (c) 1999, 2025, 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

 129     /** An output buffer for the constant pool.
 130      */
 131     ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
 132 
 133     /** The constant pool writer.
 134      */
 135     final PoolWriter poolWriter;
 136 
 137     /** The log to use for verbose output.
 138      */
 139     private final Log log;
 140 
 141     /** The name table. */
 142     private final Names names;
 143 
 144     /** Access to files. */
 145     private final JavaFileManager fileManager;
 146 
 147     /** The tags and constants used in compressed stackmap. */
 148     static final int SAME_FRAME_SIZE = 64;
 149     static final int EARLY_LARVAL = 246;
 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     @SuppressWarnings("this-escape")
 166     protected ClassWriter(Context context) {
 167         context.put(classWriterKey, this);
 168 
 169         log = Log.instance(context);

 206      *    'c' -- classes
 207      *    'f' -- fields
 208      *    'i' -- innerclass attributes
 209      *    'm' -- methods
 210      *  For example, to dump everything:
 211      *    javac -XDdumpmodifiers=cifm MyProg.java
 212      */
 213     private boolean dumpClassModifiers; // -XDdumpmodifiers=c
 214     private boolean dumpFieldModifiers; // -XDdumpmodifiers=f
 215     private boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i
 216     private boolean dumpMethodModifiers; // -XDdumpmodifiers=m
 217 
 218 
 219     /** Return flags as a string, separated by " ".
 220      */
 221     public static String flagNames(long flags) {
 222         StringBuilder sbuf = new StringBuilder();
 223         int i = 0;
 224         long f = flags & StandardFlags;
 225         while (f != 0) {
 226             if ((f & 1) != 0 && flagName[i] != "") {
 227                 sbuf.append(" ");
 228                 sbuf.append(flagName[i]);
 229             }
 230             f = f >> 1;
 231             i++;
 232         }
 233         return sbuf.toString();
 234     }
 235     //where
 236         private static final String[] flagName = {
 237             "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL",
 238             // the empty position should be for synchronized but right now we don't have any test checking it
 239             "", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE",
 240             "ABSTRACT", "STRICTFP"};
 241 
 242 /* ****************************************************************
 243  * Output routines
 244  ******************************************************************/
 245 
 246     /** Write a character into given byte buffer;
 247      *  byte buffer will not be grown.
 248      */
 249     void putChar(ByteBuffer buf, int op, int x) {
 250         buf.elems[op  ] = (byte)((x >>  8) & 0xFF);
 251         buf.elems[op+1] = (byte)((x      ) & 0xFF);
 252     }
 253 
 254     /** Write an integer into given byte buffer;
 255      *  byte buffer will not be grown.
 256      */
 257     void putInt(ByteBuffer buf, int adr, int x) {
 258         buf.elems[adr  ] = (byte)((x >> 24) & 0xFF);
 259         buf.elems[adr+1] = (byte)((x >> 16) & 0xFF);

 822         for (ProvidesDirective p : m.provides) {
 823             mergedProvides.computeIfAbsent(p.service, s -> new LinkedHashSet<>()).addAll(p.impls);
 824         }
 825         databuf.appendChar(mergedProvides.size());
 826         mergedProvides.forEach((srvc, impls) -> {
 827             databuf.appendChar(poolWriter.putClass(srvc));
 828             databuf.appendChar(impls.size());
 829             impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
 830         });
 831 
 832         endAttr(alenIdx);
 833         return 1;
 834     }
 835 
 836 /* ********************************************************************
 837  * Writing Objects
 838  **********************************************************************/
 839 
 840     /** Write "inner classes" attribute.
 841      */
 842     void writeInnerClasses(boolean markedPreview) {
 843         int alenIdx = writeAttr(names.InnerClasses);
 844         databuf.appendChar(poolWriter.innerClasses.size());
 845         for (ClassSymbol inner : poolWriter.innerClasses) {
 846             inner.markAbstractIfNeeded(types);
 847             int flags = adjustFlags(inner, inner.flags_field);
 848             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
 849             if ((flags & ACC_IDENTITY) != 0) {
 850                 if (!markedPreview) {
 851                     flags &= ~ACC_IDENTITY; // No SUPER for InnerClasses
 852                 }
 853             }
 854             if (dumpInnerClassModifiers) {
 855                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 856                 pw.println("INNERCLASS  " + inner.name);
 857                 pw.println("---" + flagNames(flags));
 858             }
 859             databuf.appendChar(poolWriter.putClass(inner));
 860             databuf.appendChar(
 861                 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
 862             databuf.appendChar(
 863                 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
 864             databuf.appendChar(flags);
 865         }
 866         endAttr(alenIdx);
 867     }
 868 
 869      /** Write out "LoadableDescriptors" attribute by enumerating the value classes encountered in field/method descriptors during this compilation.
 870       */
 871      void writeLoadableDescriptorsAttribute() {
 872         int alenIdx = writeAttr(names.LoadableDescriptors);
 873         databuf.appendChar(poolWriter.loadableDescriptors.size());
 874         for (Symbol c : poolWriter.loadableDescriptors) {
 875             databuf.appendChar(poolWriter.putDescriptor(c));
 876         }
 877         endAttr(alenIdx);
 878      }
 879 
 880     int writeRecordAttribute(ClassSymbol csym) {
 881         int alenIdx = writeAttr(names.Record);
 882         Scope s = csym.members();
 883         databuf.appendChar(csym.getRecordComponents().size());
 884         for (VarSymbol v: csym.getRecordComponents()) {
 885             //databuf.appendChar(poolWriter.putMember(v.accessor.head.snd));
 886             databuf.appendChar(poolWriter.putName(v.name));
 887             databuf.appendChar(poolWriter.putDescriptor(v));
 888             int acountIdx = beginAttrs();
 889             int acount = 0;
 890             acount += writeMemberAttrs(v, true);
 891             endAttrs(acountIdx, acount);
 892         }
 893         endAttr(alenIdx);
 894         return 1;
 895     }
 896 
 897     /**
 898      * Write NestMembers attribute (if needed)
 899      */

 973             }
 974         } while (lastBootstrapMethods < poolWriter.bootstrapMethods.size());
 975         databuf.appendChar(poolWriter.bootstrapMethods.size());
 976         for (BsmKey bsmKey : poolWriter.bootstrapMethods.keySet()) {
 977             //write BSM handle
 978             databuf.appendChar(poolWriter.putConstant(bsmKey.bsm));
 979             LoadableConstant[] uniqueArgs = bsmKey.staticArgs;
 980             //write static args length
 981             databuf.appendChar(uniqueArgs.length);
 982             //write static args array
 983             for (LoadableConstant arg : uniqueArgs) {
 984                 databuf.appendChar(poolWriter.putConstant(arg));
 985             }
 986         }
 987         endAttr(alenIdx);
 988     }
 989 
 990     /** Write field symbol, entering all references into constant pool.
 991      */
 992     void writeField(VarSymbol v) {
 993         int flags = adjustFlags(v, v.flags());
 994         databuf.appendChar(flags);
 995         if (dumpFieldModifiers) {
 996             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 997             pw.println("FIELD  " + v.name);
 998             pw.println("---" + flagNames(v.flags()));
 999         }
1000         databuf.appendChar(poolWriter.putName(v.name));
1001         databuf.appendChar(poolWriter.putDescriptor(v));
1002         Type fldType = v.erasure(types);
1003         if (fldType.requiresLoadableDescriptors(v.owner)) {
1004             poolWriter.enterLoadableDescriptorsClass(fldType.tsym);
1005             if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
1006                 preview.markUsesPreview(null);
1007             }
1008         }
1009         int acountIdx = beginAttrs();
1010         int acount = 0;
1011         if (v.getConstValue() != null) {
1012             int alenIdx = writeAttr(names.ConstantValue);
1013             databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
1014             endAttr(alenIdx);
1015             acount++;
1016         }
1017         acount += writeMemberAttrs(v, false);
1018         acount += writeExtraAttributes(v);
1019         endAttrs(acountIdx, acount);
1020     }
1021 
1022     /** Write method symbol, entering all references into constant pool.
1023      */
1024     void writeMethod(MethodSymbol m) {
1025         int flags = adjustFlags(m, m.flags());
1026         databuf.appendChar(flags);
1027         if (dumpMethodModifiers) {
1028             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1029             pw.println("METHOD  " + m.name);
1030             pw.println("---" + flagNames(m.flags()));
1031         }
1032         databuf.appendChar(poolWriter.putName(m.name));
1033         databuf.appendChar(poolWriter.putDescriptor(m));
1034         MethodType mtype = (MethodType) m.externalType(types);
1035         for (Type t : mtype.getParameterTypes()) {
1036             if (t.requiresLoadableDescriptors(m.owner)) {
1037                 poolWriter.enterLoadableDescriptorsClass(t.tsym);
1038                 if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
1039                     preview.markUsesPreview(null);
1040                 }
1041             }
1042         }
1043         Type returnType = mtype.getReturnType();
1044         if (returnType.requiresLoadableDescriptors(m.owner)) {
1045             poolWriter.enterLoadableDescriptorsClass(returnType.tsym);
1046             if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
1047                 preview.markUsesPreview(null);
1048             }
1049         }
1050         int acountIdx = beginAttrs();
1051         int acount = 0;
1052         if (m.code != null) {
1053             int alenIdx = writeAttr(names.Code);
1054             writeCode(m.code);
1055             m.code = null; // to conserve space
1056             endAttr(alenIdx);
1057             acount++;
1058         }
1059         List<Type> thrown = m.erasure(types).getThrownTypes();
1060         if (thrown.nonEmpty()) {
1061             int alenIdx = writeAttr(names.Exceptions);
1062             databuf.appendChar(thrown.length());
1063             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1064                 databuf.appendChar(poolWriter.putClass(l.head));
1065             endAttr(alenIdx);
1066             acount++;
1067         }
1068         if (m.defaultValue != null) {
1069             int alenIdx = writeAttr(names.AnnotationDefault);

1320                 break;
1321             case UNINITIALIZED_THIS:
1322                 if (debugstackmap) System.out.print("uninit_this");
1323                 databuf.appendByte(6);
1324                 break;
1325             case UNINITIALIZED_OBJECT:
1326                 { UninitializedType uninitType = (UninitializedType)t;
1327                 databuf.appendByte(8);
1328                 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1329                 databuf.appendChar(uninitType.offset);
1330                 }
1331                 break;
1332             default:
1333                 throw new AssertionError();
1334             }
1335         }
1336 
1337     /** An entry in the JSR202 StackMapTable */
1338     abstract static class StackMapTableFrame {
1339         abstract int getFrameType();
1340         int pc;
1341 
1342         StackMapTableFrame(int pc) {
1343             this.pc = pc;
1344         }
1345 
1346         void write(ClassWriter writer) {
1347             int frameType = getFrameType();
1348             writer.databuf.appendByte(frameType);
1349             if (writer.debugstackmap) System.out.println(" frame_type=" + frameType + " bytecode offset " + pc);
1350         }
1351 
1352         static class SameFrame extends StackMapTableFrame {
1353             final int offsetDelta;
1354             SameFrame(int pc, int offsetDelta) {
1355                 super(pc);
1356                 this.offsetDelta = offsetDelta;
1357             }
1358             int getFrameType() {
1359                 return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta : SAME_FRAME_EXTENDED;
1360             }
1361             @Override
1362             void write(ClassWriter writer) {
1363                 super.write(writer);
1364                 if (getFrameType() == SAME_FRAME_EXTENDED) {
1365                     writer.databuf.appendChar(offsetDelta);
1366                     if (writer.debugstackmap){
1367                         System.out.print(" offset_delta=" + offsetDelta);
1368                     }
1369                 }
1370             }
1371         }
1372 
1373         static class SameLocals1StackItemFrame extends StackMapTableFrame {
1374             final int offsetDelta;
1375             final Type stack;
1376             SameLocals1StackItemFrame(int pc, int offsetDelta, Type stack) {
1377                 super(pc);
1378                 this.offsetDelta = offsetDelta;
1379                 this.stack = stack;
1380             }
1381             int getFrameType() {
1382                 return (offsetDelta < SAME_FRAME_SIZE) ?
1383                        (SAME_FRAME_SIZE + offsetDelta) :
1384                        SAME_LOCALS_1_STACK_ITEM_EXTENDED;
1385             }
1386             @Override
1387             void write(ClassWriter writer) {
1388                 super.write(writer);
1389                 if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
1390                     writer.databuf.appendChar(offsetDelta);
1391                     if (writer.debugstackmap) {
1392                         System.out.print(" offset_delta=" + offsetDelta);
1393                     }
1394                 }
1395                 if (writer.debugstackmap) {
1396                     System.out.print(" stack[" + 0 + "]=");
1397                 }
1398                 writer.writeStackMapType(stack);
1399             }
1400         }
1401 
1402         static class ChopFrame extends StackMapTableFrame {
1403             final int frameType;
1404             final int offsetDelta;
1405             ChopFrame(int pc, int frameType, int offsetDelta) {
1406                 super(pc);
1407                 this.frameType = frameType;
1408                 this.offsetDelta = offsetDelta;
1409             }
1410             int getFrameType() { return frameType; }
1411             @Override
1412             void write(ClassWriter writer) {
1413                 super.write(writer);
1414                 writer.databuf.appendChar(offsetDelta);
1415                 if (writer.debugstackmap) {
1416                     System.out.print(" offset_delta=" + offsetDelta);
1417                 }
1418             }
1419         }
1420 
1421         static class AppendFrame extends StackMapTableFrame {
1422             final int frameType;
1423             final int offsetDelta;
1424             final Type[] locals;
1425             AppendFrame(int pc, int frameType, int offsetDelta, Type[] locals) {
1426                 super(pc);
1427                 this.frameType = frameType;
1428                 this.offsetDelta = offsetDelta;
1429                 this.locals = locals;
1430             }
1431             int getFrameType() { return frameType; }
1432             @Override
1433             void write(ClassWriter writer) {
1434                 super.write(writer);
1435                 writer.databuf.appendChar(offsetDelta);
1436                 if (writer.debugstackmap) {
1437                     System.out.print(" offset_delta=" + offsetDelta);
1438                 }
1439                 for (int i=0; i<locals.length; i++) {
1440                      if (writer.debugstackmap) System.out.print(" locals[" + i + "]=");
1441                      writer.writeStackMapType(locals[i]);
1442                 }
1443             }
1444         }
1445 
1446         static class FullFrame extends StackMapTableFrame {
1447             final int offsetDelta;
1448             final Type[] locals;
1449             final Type[] stack;
1450             FullFrame(int pc, int offsetDelta, Type[] locals, Type[] stack) {
1451                 super(pc);
1452                 this.offsetDelta = offsetDelta;
1453                 this.locals = locals;
1454                 this.stack = stack;
1455             }
1456             int getFrameType() { return FULL_FRAME; }
1457             @Override
1458             void write(ClassWriter writer) {
1459                 super.write(writer);
1460                 writer.databuf.appendChar(offsetDelta);
1461                 writer.databuf.appendChar(locals.length);
1462                 if (writer.debugstackmap) {
1463                     System.out.print(" offset_delta=" + offsetDelta);
1464                     System.out.print(" nlocals=" + locals.length);
1465                 }
1466                 for (int i=0; i<locals.length; i++) {
1467                     if (writer.debugstackmap) System.out.print(" locals[" + i + "]=");
1468                     writer.writeStackMapType(locals[i]);
1469                 }
1470 
1471                 writer.databuf.appendChar(stack.length);
1472                 if (writer.debugstackmap) { System.out.print(" nstack=" + stack.length); }
1473                 for (int i=0; i<stack.length; i++) {
1474                     if (writer.debugstackmap) System.out.print(" stack[" + i + "]=");
1475                     writer.writeStackMapType(stack[i]);
1476                 }
1477             }
1478         }
1479 
1480         static class EarlyLarvalFrame extends StackMapTableFrame {
1481             final StackMapTableFrame base;
1482             Set<VarSymbol> unsetFields;
1483 
1484             EarlyLarvalFrame(StackMapTableFrame base, Set<VarSymbol> unsetFields) {
1485                 super(base.pc);
1486                 Assert.check(!(base instanceof EarlyLarvalFrame));
1487                 this.base = base;
1488                 this.unsetFields = unsetFields == null ? Set.of() : unsetFields;
1489             }
1490 
1491             int getFrameType() { return EARLY_LARVAL; }
1492 
1493             @Override
1494             void write(ClassWriter writer) {
1495                 super.write(writer);
1496                 writer.databuf.appendChar(unsetFields.size());
1497                 if (writer.debugstackmap) {
1498                     System.out.println("    # writing: EarlyLarval stackmap frame with " + unsetFields.size() + " fields");
1499                 }
1500                 for (VarSymbol vsym : unsetFields) {
1501                     int index = writer.poolWriter.putNameAndType(vsym);
1502                     writer.databuf.appendChar(index);
1503                     if (writer.debugstackmap) {
1504                         System.out.println("    #writing unset field: " + index + ", with name: " + vsym.name.toString());
1505                     }
1506                 }
1507                 base.write(writer);
1508             }
1509         }
1510 
1511        /** Compare this frame with the previous frame and produce
1512         *  an entry of compressed stack map frame. */
1513         static StackMapTableFrame getInstance(Code.StackMapFrame this_frame,
1514                                               Code.StackMapFrame prevFrame,
1515                                               Types types,
1516                                               int pc) {
1517             Type[] locals = this_frame.locals;
1518             Type[] stack = this_frame.stack;
1519             int offset_delta = this_frame.pc - prevFrame.pc - 1;
1520             if (stack.length == 1) {
1521                 if (locals.length == prevFrame.locals.length
1522                     && compare(prevFrame.locals, locals, types) == 0) {
1523                     return new SameLocals1StackItemFrame(pc, offset_delta, stack[0]);
1524                 }
1525             } else if (stack.length == 0) {
1526                 int diff_length = compare(prevFrame.locals, locals, types);
1527                 if (diff_length == 0) {
1528                     return new SameFrame(pc, offset_delta);
1529                 } else if (-MAX_LOCAL_LENGTH_DIFF < diff_length && diff_length < 0) {
1530                     // APPEND
1531                     Type[] local_diff = new Type[-diff_length];
1532                     for (int i=prevFrame.locals.length, j=0; i<locals.length; i++,j++) {
1533                         local_diff[j] = locals[i];
1534                     }
1535                     return new AppendFrame(pc, SAME_FRAME_EXTENDED - diff_length,
1536                                            offset_delta,
1537                                            local_diff);
1538                 } else if (0 < diff_length && diff_length < MAX_LOCAL_LENGTH_DIFF) {
1539                     // CHOP
1540                     return new ChopFrame(pc, SAME_FRAME_EXTENDED - diff_length,
1541                                          offset_delta);
1542                 }
1543             }
1544             // FULL_FRAME
1545             return new FullFrame(pc, offset_delta, locals, stack);
1546         }
1547 
1548         static boolean isInt(Type t) {
1549             return (t.getTag().isStrictSubRangeOf(INT)  || t.hasTag(BOOLEAN));
1550         }
1551 
1552         static boolean isSameType(Type t1, Type t2, Types types) {
1553             if (t1 == null) { return t2 == null; }
1554             if (t2 == null) { return false; }
1555 
1556             if (isInt(t1) && isInt(t2)) { return true; }
1557 
1558             if (t1.hasTag(UNINITIALIZED_THIS)) {
1559                 return t2.hasTag(UNINITIALIZED_THIS);
1560             } else if (t1.hasTag(UNINITIALIZED_OBJECT)) {
1561                 if (t2.hasTag(UNINITIALIZED_OBJECT)) {
1562                     return ((UninitializedType)t1).offset == ((UninitializedType)t2).offset;
1563                 } else {
1564                     return false;
1565                 }

1648         }
1649         return outFile; // may be null if write failed
1650     }
1651 
1652     /** Write class `c' to outstream `out'.
1653      */
1654     public void writeClassFile(OutputStream out, ClassSymbol c)
1655         throws IOException, PoolOverflow, StringOverflow {
1656         Assert.check((c.flags() & COMPOUND) == 0);
1657         databuf.reset();
1658         poolbuf.reset();
1659 
1660         Type supertype = types.supertype(c.type);
1661         List<Type> interfaces = types.interfaces(c.type);
1662         List<Type> typarams = c.type.getTypeArguments();
1663 
1664         int flags;
1665         if (c.owner.kind == MDL) {
1666             flags = ACC_MODULE;
1667         } else {
1668             long originalFlags = c.flags();
1669             flags = adjustFlags(c, c.flags() & ~(DEFAULT | STRICTFP));
1670             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1671             flags = flags & ClassFlags;
1672             flags |= (originalFlags & IDENTITY_TYPE) != 0 ? ACC_IDENTITY : flags;
1673         }
1674 
1675         if (dumpClassModifiers) {
1676             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1677             pw.println();
1678             pw.println("CLASSFILE  " + c.getQualifiedName());
1679             pw.println("---" + flagNames(flags));
1680         }
1681         databuf.appendChar(flags);
1682 
1683         if (c.owner.kind == MDL) {
1684             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1685             databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1686         } else {
1687             databuf.appendChar(poolWriter.putClass(c));
1688         }
1689         databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1690         databuf.appendChar(interfaces.length());
1691         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1692             databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));

1746             acount++;
1747             // Append CompilationID attribute
1748             alenIdx = writeAttr(names.CompilationID);
1749             databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(System.currentTimeMillis()))));
1750             endAttr(alenIdx);
1751             acount++;
1752         }
1753 
1754         acount += writeFlagAttrs(c.flags());
1755         acount += writeJavaAnnotations(c.getRawAttributes());
1756         acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
1757         acount += writeEnclosingMethodAttribute(c);
1758         if (c.owner.kind == MDL) {
1759             acount += writeModuleAttribute(c);
1760             acount += writeFlagAttrs(c.owner.flags() & ~DEPRECATED);
1761         }
1762         acount += writeExtraClassAttributes(c);
1763         acount += writeExtraAttributes(c);
1764 
1765         poolbuf.appendInt(JAVA_MAGIC);
1766         boolean markedPreview = preview.isEnabled() && preview.usesPreview(c.sourcefile);
1767         if (markedPreview) {
1768             poolbuf.appendChar(ClassFile.PREVIEW_MINOR_VERSION);
1769         } else {
1770             poolbuf.appendChar(target.minorVersion);
1771         }
1772         poolbuf.appendChar(target.majorVersion);
1773 
1774         if (c.owner.kind != MDL) {
1775             if (target.hasNestmateAccess()) {
1776                 acount += writeNestMembersIfNeeded(c);
1777                 acount += writeNestHostIfNeeded(c);
1778             }
1779         }
1780 
1781         if (c.isRecord()) {
1782             acount += writeRecordAttribute(c);
1783         }
1784 
1785         if (target.hasSealedClasses()) {
1786             acount += writePermittedSubclassesIfNeeded(c);
1787         }
1788 
1789         if (!poolWriter.bootstrapMethods.isEmpty()) {
1790             writeBootstrapMethods();
1791             acount++;
1792         }
1793 
1794         if (!poolWriter.innerClasses.isEmpty()) {
1795             writeInnerClasses(markedPreview);
1796             acount++;
1797         }
1798 
1799         if (!poolWriter.loadableDescriptors.isEmpty()) {
1800             writeLoadableDescriptorsAttribute();
1801             acount++;
1802         }
1803 
1804         endAttrs(acountIdx, acount);
1805 
1806         out.write(poolbuf.elems, 0, poolbuf.length);
1807 
1808         poolWriter.writePool(out);
1809         poolWriter.reset(); // to save space
1810 
1811         out.write(databuf.elems, 0, databuf.length);
1812     }
1813 
1814      /**Allows subclasses to write additional class attributes
1815       *
1816       * @return the number of attributes written
1817       */
1818     protected int writeExtraClassAttributes(ClassSymbol c) {
1819         return 0;
1820     }
1821 
1822     /**Allows friends to write additional attributes
1823      *
1824      * @return the number of attributes written
1825      */
1826     protected int writeExtraAttributes(Symbol sym) {
1827         int i = 0;
1828         for (ToIntFunction<Symbol> hook : extraAttributeHooks) {
1829             i += hook.applyAsInt(sym);
1830         }
1831         return i;
1832     }
1833 
1834     int adjustFlags(Symbol sym, final long flags) {
1835         int result = (int)flags;
1836 
1837         // Elide strictfp bit in class files
1838         if (target.obsoleteAccStrict())
1839             result &= ~STRICTFP;
1840 
1841         if ((flags & BRIDGE) != 0)
1842             result |= ACC_BRIDGE;
1843         if ((flags & VARARGS) != 0)
1844             result |= ACC_VARARGS;
1845         if ((flags & DEFAULT) != 0)
1846             result &= ~ABSTRACT;
1847         if ((flags & IDENTITY_TYPE) != 0) {
1848             result |= ACC_IDENTITY;
1849         }
1850         if (sym.kind == VAR) {
1851             if ((flags & STRICT) != 0) {
1852                 result |= ACC_STRICT;
1853             }
1854         }
1855         return result;
1856     }
1857 
1858     long getLastModified(FileObject filename) {
1859         return filename.getLastModified();
1860     }
1861 }
< prev index next >