< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 1999, 2019, 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 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 
  34 import javax.tools.JavaFileManager;
  35 import javax.tools.FileObject;
  36 import javax.tools.JavaFileManager.Location;
  37 import javax.tools.JavaFileObject;
  38 
  39 import com.sun.tools.javac.code.*;
  40 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  41 import com.sun.tools.javac.code.Directive.*;
  42 import com.sun.tools.javac.code.Symbol.*;
  43 import com.sun.tools.javac.code.Type.*;
  44 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;

  45 import com.sun.tools.javac.comp.Check;
  46 import com.sun.tools.javac.file.PathFileObject;
  47 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
  48 import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;


  49 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  50 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  51 import com.sun.tools.javac.util.*;
  52 
  53 import static com.sun.tools.javac.code.Flags.*;
  54 import static com.sun.tools.javac.code.Kinds.Kind.*;
  55 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  56 import static com.sun.tools.javac.code.TypeTag.*;
  57 import static com.sun.tools.javac.main.Option.*;
  58 
  59 import static javax.tools.StandardLocation.CLASS_OUTPUT;
  60 
  61 /** This class provides operations to map an internal symbol table graph
  62  *  rooted in a ClassSymbol into a classfile.
  63  *
  64  *  <p><b>This is NOT part of any supported API.
  65  *  If you write code that depends on this, you do so at your own risk.
  66  *  This code and its internal interfaces are subject to change or
  67  *  deletion without notice.</b>
  68  */


  99     /**
 100      * Source language version.
 101      */
 102     private Source source;
 103 
 104     /** Type utilities. */
 105     private Types types;
 106 
 107     private Check check;
 108 
 109     /**
 110      * If true, class files will be written in module-specific subdirectories
 111      * of the CLASS_OUTPUT location.
 112      */
 113     public boolean multiModuleMode;
 114 
 115     /** The initial sizes of the data and constant pool buffers.
 116      *  Sizes are increased when buffers get full.
 117      */
 118     static final int DATA_BUF_SIZE = 0x0fff0;
 119     static final int CLASS_BUF_SIZE = 0x1fff0;
 120 
 121     /** An output buffer for member info.
 122      */
 123     ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
 124 
 125     /** An output buffer for the constant pool.
 126      */
 127     ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
 128 
 129     /** The constant pool writer.
 130      */
 131     final PoolWriter poolWriter;














 132 
 133     /** The log to use for verbose output.
 134      */
 135     private final Log log;
 136 
 137     /** The name table. */
 138     private final Names names;
 139 



 140     /** Access to files. */
 141     private final JavaFileManager fileManager;
 142 





 143     /** The tags and constants used in compressed stackmap. */
 144     static final int SAME_FRAME_SIZE = 64;
 145     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 146     static final int SAME_FRAME_EXTENDED = 251;
 147     static final int FULL_FRAME = 255;
 148     static final int MAX_LOCAL_LENGTH_DIFF = 4;
 149 
 150     /** Get the ClassWriter instance for this context. */
 151     public static ClassWriter instance(Context context) {
 152         ClassWriter instance = context.get(classWriterKey);
 153         if (instance == null)
 154             instance = new ClassWriter(context);
 155         return instance;
 156     }
 157 
 158     /** Construct a class writer, given an options table.
 159      */
 160     protected ClassWriter(Context context) {
 161         context.put(classWriterKey, this);
 162 
 163         log = Log.instance(context);
 164         names = Names.instance(context);

 165         options = Options.instance(context);
 166         preview = Preview.instance(context);
 167         target = Target.instance(context);
 168         source = Source.instance(context);
 169         types = Types.instance(context);
 170         check = Check.instance(context);
 171         fileManager = context.get(JavaFileManager.class);
 172         poolWriter = Gen.instance(context).poolWriter;

 173 
 174         verbose        = options.isSet(VERBOSE);
 175         genCrt         = options.isSet(XJCOV);
 176         debugstackmap = options.isSet("debug.stackmap");
 177 
 178         emitSourceFile = options.isUnset(G_CUSTOM) ||
 179                             options.isSet(G_CUSTOM, "source");
 180 
 181         String modifierFlags = options.get("debug.dumpmodifiers");
 182         if (modifierFlags != null) {
 183             dumpClassModifiers = modifierFlags.indexOf('c') != -1;
 184             dumpFieldModifiers = modifierFlags.indexOf('f') != -1;
 185             dumpInnerClassModifiers = modifierFlags.indexOf('i') != -1;
 186             dumpMethodModifiers = modifierFlags.indexOf('m') != -1;
 187         }
 188     }
 189 
 190 /******************************************************************
 191  * Diagnostics: dump generated class names and modifiers
 192  ******************************************************************/


 233  ******************************************************************/
 234 
 235     /** Write a character into given byte buffer;
 236      *  byte buffer will not be grown.
 237      */
 238     void putChar(ByteBuffer buf, int op, int x) {
 239         buf.elems[op  ] = (byte)((x >>  8) & 0xFF);
 240         buf.elems[op+1] = (byte)((x      ) & 0xFF);
 241     }
 242 
 243     /** Write an integer into given byte buffer;
 244      *  byte buffer will not be grown.
 245      */
 246     void putInt(ByteBuffer buf, int adr, int x) {
 247         buf.elems[adr  ] = (byte)((x >> 24) & 0xFF);
 248         buf.elems[adr+1] = (byte)((x >> 16) & 0xFF);
 249         buf.elems[adr+2] = (byte)((x >>  8) & 0xFF);
 250         buf.elems[adr+3] = (byte)((x      ) & 0xFF);
 251     }
 252 



























































































 253 /******************************************************************
 254  * Writing the Constant Pool
 255  ******************************************************************/
 256 
 257     /** Thrown when the constant pool is over full.
 258      */
 259     public static class PoolOverflow extends RuntimeException {
 260         private static final long serialVersionUID = 0;
 261         public PoolOverflow() {}
 262     }
 263     public static class StringOverflow extends RuntimeException {
 264         private static final long serialVersionUID = 0;
 265         public final String value;
 266         public StringOverflow(String s) {
 267             value = s;
 268         }
 269     }
 270 

























































































































































 271 /******************************************************************
 272  * Writing Attributes
 273  ******************************************************************/
 274 
 275     /** Write header for an attribute to data buffer and return
 276      *  position past attribute length index.
 277      */
 278     int writeAttr(Name attrName) {
 279         int index = poolWriter.putName(attrName);
 280         databuf.appendChar(index);
 281         databuf.appendInt(0);
 282         return databuf.length;
 283     }
 284 
 285     /** Fill in attribute length.
 286      */
 287     void endAttr(int index) {
 288         putInt(databuf, index - 4, databuf.length - index);
 289     }
 290 
 291     /** Leave space for attribute count and return index for
 292      *  number of attributes field.
 293      */
 294     int beginAttrs() {
 295         databuf.appendChar(0);
 296         return databuf.length;
 297     }
 298 
 299     /** Fill in number of attributes.
 300      */


 306      *  Returns the number of attributes written (0 or 1).
 307      */
 308     int writeEnclosingMethodAttribute(ClassSymbol c) {
 309         return writeEnclosingMethodAttribute(names.EnclosingMethod, c);
 310     }
 311 
 312     /** Write the EnclosingMethod attribute with a specified name.
 313      *  Returns the number of attributes written (0 or 1).
 314      */
 315     protected int writeEnclosingMethodAttribute(Name attributeName, ClassSymbol c) {
 316         if (c.owner.kind != MTH && // neither a local class
 317             c.name != names.empty) // nor anonymous
 318             return 0;
 319 
 320         int alenIdx = writeAttr(attributeName);
 321         ClassSymbol enclClass = c.owner.enclClass();
 322         MethodSymbol enclMethod =
 323             (c.owner.type == null // local to init block
 324              || c.owner.kind != MTH) // or member init
 325             ? null
 326             : ((MethodSymbol)c.owner).originalEnclosingMethod();
 327         databuf.appendChar(poolWriter.putClass(enclClass));
 328         databuf.appendChar(enclMethod == null ? 0 : poolWriter.putNameAndType(enclMethod));
 329         endAttr(alenIdx);
 330         return 1;
 331     }
 332 
 333     /** Write flag attributes; return number of attributes written.
 334      */
 335     int writeFlagAttrs(long flags) {
 336         int acount = 0;
 337         if ((flags & DEPRECATED) != 0) {
 338             int alenIdx = writeAttr(names.Deprecated);
 339             endAttr(alenIdx);
 340             acount++;
 341         }
 342         return acount;
 343     }
 344 
 345     /** Write member (field or method) attributes;
 346      *  return number of attributes written.
 347      */
 348     int writeMemberAttrs(Symbol sym) {
 349         int acount = writeFlagAttrs(sym.flags());
 350         long flags = sym.flags();
 351         if ((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
 352             (flags & ANONCONSTR) == 0 &&
 353             (!types.isSameType(sym.type, sym.erasure(types)) ||
 354              poolWriter.signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
 355             // note that a local class with captured variables
 356             // will get a signature attribute
 357             int alenIdx = writeAttr(names.Signature);
 358             databuf.appendChar(poolWriter.putSignature(sym));
 359             endAttr(alenIdx);
 360             acount++;
 361         }
 362         acount += writeJavaAnnotations(sym.getRawAttributes());
 363         acount += writeTypeAnnotations(sym.getRawTypeAttributes(), false);
 364         return acount;
 365     }
 366 
 367     /**
 368      * Write method parameter names attribute.
 369      */
 370     int writeMethodParametersAttr(MethodSymbol m) {
 371         MethodType ty = m.externalType(types).asMethodType();
 372         final int allparams = ty.argtypes.size();
 373         if (m.params != null && allparams != 0) {
 374             final int attrIndex = writeAttr(names.MethodParameters);
 375             databuf.appendByte(allparams);
 376             // Write extra parameters first
 377             for (VarSymbol s : m.extraParams) {
 378                 final int flags =
 379                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
 380                     ((int) m.flags() & SYNTHETIC);
 381                 databuf.appendChar(poolWriter.putName(s.name));
 382                 databuf.appendChar(flags);
 383             }
 384             // Now write the real parameters
 385             for (VarSymbol s : m.params) {
 386                 final int flags =
 387                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
 388                     ((int) m.flags() & SYNTHETIC);
 389                 databuf.appendChar(poolWriter.putName(s.name));
 390                 databuf.appendChar(flags);
 391             }
 392             // Now write the captured locals
 393             for (VarSymbol s : m.capturedLocals) {
 394                 final int flags =
 395                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
 396                     ((int) m.flags() & SYNTHETIC);
 397                 databuf.appendChar(poolWriter.putName(s.name));
 398                 databuf.appendChar(flags);
 399             }
 400             endAttr(attrIndex);
 401             return 1;
 402         } else
 403             return 0;
 404     }
 405 
 406 
 407     private void writeParamAnnotations(List<VarSymbol> params,
 408                                        RetentionPolicy retention) {
 409         for (VarSymbol s : params) {
 410             ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
 411             for (Attribute.Compound a : s.getRawAttributes())
 412                 if (types.getRetention(a) == retention)
 413                     buf.append(a);
 414             databuf.appendChar(buf.length());
 415             for (Attribute.Compound a : buf)
 416                 writeCompoundAttribute(a);
 417         }


 509             if (tc.hasUnknownPosition()) {
 510                 boolean fixed = tc.tryFixPosition();
 511 
 512                 // Could we fix it?
 513                 if (!fixed) {
 514                     // This happens for nested types like @A Outer. @B Inner.
 515                     // For method parameters we get the annotation twice! Once with
 516                     // a valid position, once unknown.
 517                     // TODO: find a cleaner solution.
 518                     PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 519                     pw.println("ClassWriter: Position UNKNOWN in type annotation: " + tc);
 520                     continue;
 521                 }
 522             }
 523 
 524             if (tc.position.type.isLocal() != inCode)
 525                 continue;
 526             if (!tc.position.emitToClassfile())
 527                 continue;
 528             switch (types.getRetention(tc)) {
 529             case SOURCE: break;
 530             case CLASS: invisibles.append(tc); break;
 531             case RUNTIME: visibles.append(tc); break;
 532             default: // /* fail soft */ throw new AssertionError(vis);
 533             }
 534         }
 535 
 536         int attrCount = 0;
 537         if (visibles.length() != 0) {
 538             int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations);
 539             databuf.appendChar(visibles.length());
 540             for (Attribute.TypeCompound p : visibles)
 541                 writeTypeAnnotation(p);
 542             endAttr(attrIndex);
 543             attrCount++;
 544         }
 545 
 546         if (invisibles.length() != 0) {
 547             int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations);
 548             databuf.appendChar(invisibles.length());
 549             for (Attribute.TypeCompound p : invisibles)
 550                 writeTypeAnnotation(p);
 551             endAttr(attrIndex);
 552             attrCount++;
 553         }
 554 
 555         return attrCount;
 556     }
 557 
 558     /** A visitor to write an attribute including its leading
 559      *  single-character marker.
 560      */
 561     class AttributeWriter implements Attribute.Visitor {
 562         public void visitConstant(Attribute.Constant _value) {
 563             if (_value.type.getTag() == CLASS) {
 564                 Assert.check(_value.value instanceof String);
 565                 String s = (String)_value.value;

























 566                 databuf.appendByte('s');
 567                 databuf.appendChar(poolWriter.putName(names.fromString(s)));
 568             } else {
 569                 switch (_value.type.getTag()) {
 570                     case BYTE:
 571                         databuf.appendByte('B');
 572                         break;
 573                     case CHAR:
 574                         databuf.appendByte('C');
 575                         break;
 576                     case SHORT:
 577                         databuf.appendByte('S');
 578                         break;
 579                     case INT:
 580                         databuf.appendByte('I');
 581                         break;
 582                     case LONG:
 583                         databuf.appendByte('J');
 584                         break;
 585                     case FLOAT:
 586                         databuf.appendByte('F');
 587                         break;
 588                     case DOUBLE:
 589                         databuf.appendByte('D');
 590                         break;
 591                     case BOOLEAN:
 592                         databuf.appendByte('Z');
 593                         break;
 594                     default:
 595                         throw new AssertionError(_value.type);
 596                 }
 597                 databuf.appendChar(poolWriter.putConstant(_value.value));
 598             }

 599         }
 600         public void visitEnum(Attribute.Enum e) {
 601             databuf.appendByte('e');
 602             databuf.appendChar(poolWriter.putDescriptor(e.value.type));
 603             databuf.appendChar(poolWriter.putName(e.value.name));
 604         }
 605         public void visitClass(Attribute.Class clazz) {
 606             databuf.appendByte('c');
 607             databuf.appendChar(poolWriter.putDescriptor(clazz.classType));
 608         }
 609         public void visitCompound(Attribute.Compound compound) {
 610             databuf.appendByte('@');
 611             writeCompoundAttribute(compound);
 612         }
 613         public void visitError(Attribute.Error x) {
 614             throw new AssertionError(x);
 615         }
 616         public void visitArray(Attribute.Array array) {
 617             databuf.appendByte('[');
 618             databuf.appendChar(array.values.length);
 619             for (Attribute a : array.values) {
 620                 a.accept(this);
 621             }
 622         }
 623     }
 624     AttributeWriter awriter = new AttributeWriter();
 625 
 626     /** Write a compound attribute excluding the '@' marker. */
 627     void writeCompoundAttribute(Attribute.Compound c) {
 628         databuf.appendChar(poolWriter.putDescriptor(c.type));
 629         databuf.appendChar(c.values.length());
 630         for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
 631             databuf.appendChar(poolWriter.putName(p.fst.name));
 632             p.snd.accept(awriter);
 633         }
 634     }
 635 
 636     void writeTypeAnnotation(Attribute.TypeCompound c) {
 637         writePosition(c.position);
 638         writeCompoundAttribute(c);
 639     }
 640 
 641     void writePosition(TypeAnnotationPosition p) {
 642         databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte
 643         switch (p.type) {
 644         // instanceof
 645         case INSTANCEOF:
 646         // new expression
 647         case NEW:
 648         // constructor/method reference receiver
 649         case CONSTRUCTOR_REFERENCE:
 650         case METHOD_REFERENCE:
 651             databuf.appendChar(p.offset);


 715         { // Append location data for generics/arrays.
 716             databuf.appendByte(p.location.size());
 717             java.util.List<Integer> loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location);
 718             for (int i : loc)
 719                 databuf.appendByte((byte)i);
 720         }
 721     }
 722 
 723 /**********************************************************************
 724  * Writing module attributes
 725  **********************************************************************/
 726 
 727     /** Write the Module attribute if needed.
 728      *  Returns the number of attributes written (0 or 1).
 729      */
 730     int writeModuleAttribute(ClassSymbol c) {
 731         ModuleSymbol m = (ModuleSymbol) c.owner;
 732 
 733         int alenIdx = writeAttr(names.Module);
 734 
 735         databuf.appendChar(poolWriter.putModule(m));
 736         databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
 737         databuf.appendChar(m.version != null ? poolWriter.putName(m.version) : 0);
 738 
 739         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
 740         for (RequiresDirective r: m.requires) {
 741             if (!r.flags.contains(RequiresFlag.EXTRA))
 742                 requires.add(r);
 743         }
 744         databuf.appendChar(requires.size());
 745         for (RequiresDirective r: requires) {
 746             databuf.appendChar(poolWriter.putModule(r.module));
 747             databuf.appendChar(RequiresFlag.value(r.flags));
 748             databuf.appendChar(r.module.version != null ? poolWriter.putName(r.module.version) : 0);
 749         }
 750 
 751         List<ExportsDirective> exports = m.exports;
 752         databuf.appendChar(exports.size());
 753         for (ExportsDirective e: exports) {
 754             databuf.appendChar(poolWriter.putPackage(e.packge));
 755             databuf.appendChar(ExportsFlag.value(e.flags));
 756             if (e.modules == null) {
 757                 databuf.appendChar(0);
 758             } else {
 759                 databuf.appendChar(e.modules.size());
 760                 for (ModuleSymbol msym: e.modules) {
 761                     databuf.appendChar(poolWriter.putModule(msym));
 762                 }
 763             }
 764         }
 765 
 766         List<OpensDirective> opens = m.opens;
 767         databuf.appendChar(opens.size());
 768         for (OpensDirective o: opens) {
 769             databuf.appendChar(poolWriter.putPackage(o.packge));
 770             databuf.appendChar(OpensFlag.value(o.flags));
 771             if (o.modules == null) {
 772                 databuf.appendChar(0);
 773             } else {
 774                 databuf.appendChar(o.modules.size());
 775                 for (ModuleSymbol msym: o.modules) {
 776                     databuf.appendChar(poolWriter.putModule(msym));
 777                 }
 778             }
 779         }
 780 
 781         List<UsesDirective> uses = m.uses;
 782         databuf.appendChar(uses.size());
 783         for (UsesDirective s: uses) {
 784             databuf.appendChar(poolWriter.putClass(s.service));
 785         }
 786 
 787         // temporary fix to merge repeated provides clause for same service;
 788         // eventually this should be disallowed when analyzing the module,
 789         // so that each service type only appears once.
 790         Map<ClassSymbol, Set<ClassSymbol>> mergedProvides = new LinkedHashMap<>();
 791         for (ProvidesDirective p : m.provides) {
 792             mergedProvides.computeIfAbsent(p.service, s -> new LinkedHashSet<>()).addAll(p.impls);
 793         }
 794         databuf.appendChar(mergedProvides.size());
 795         mergedProvides.forEach((srvc, impls) -> {
 796             databuf.appendChar(poolWriter.putClass(srvc));
 797             databuf.appendChar(impls.size());
 798             impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
 799         });
 800 
 801         endAttr(alenIdx);
 802         return 1;
 803     }
 804 
 805 /**********************************************************************
 806  * Writing Objects
 807  **********************************************************************/
 808 






























 809     /** Write "inner classes" attribute.
 810      */
 811     void writeInnerClasses() {
 812         int alenIdx = writeAttr(names.InnerClasses);
 813         databuf.appendChar(poolWriter.innerClasses.size());
 814         for (ClassSymbol inner : poolWriter.innerClasses) {



 815             inner.markAbstractIfNeeded(types);
 816             char flags = (char) adjustFlags(inner.flags_field);
 817             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
 818             flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.
 819             if (dumpInnerClassModifiers) {
 820                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 821                 pw.println("INNERCLASS  " + inner.name);
 822                 pw.println("---" + flagNames(flags));
 823             }
 824             databuf.appendChar(poolWriter.putClass(inner));
 825             databuf.appendChar(
 826                 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
 827             databuf.appendChar(
 828                 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
 829             databuf.appendChar(flags);
 830         }
 831         endAttr(alenIdx);
 832     }
 833 
 834     /**
 835      * Write NestMembers attribute (if needed)
 836      */
 837     int writeNestMembersIfNeeded(ClassSymbol csym) {
 838         ListBuffer<ClassSymbol> nested = new ListBuffer<>();
 839         listNested(csym, nested);
 840         Set<ClassSymbol> nestedUnique = new LinkedHashSet<>(nested);
 841         if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
 842             int alenIdx = writeAttr(names.NestMembers);
 843             databuf.appendChar(nestedUnique.size());
 844             for (ClassSymbol s : nestedUnique) {
 845                 databuf.appendChar(poolWriter.putClass(s));
 846             }
 847             endAttr(alenIdx);
 848             return 1;
 849         }
 850         return 0;
 851     }
 852 
 853     /**
 854      * Write NestHost attribute (if needed)
 855      */
 856     int writeNestHostIfNeeded(ClassSymbol csym) {
 857         if (csym.owner.kind != PCK) {
 858             int alenIdx = writeAttr(names.NestHost);
 859             databuf.appendChar(poolWriter.putClass(csym.outermostClass()));
 860             endAttr(alenIdx);
 861             return 1;
 862         }
 863         return 0;
 864     }
 865 
 866     private void listNested(Symbol sym, ListBuffer<ClassSymbol> seen) {
 867         if (sym.kind != TYP) return;
 868         ClassSymbol csym = (ClassSymbol)sym;
 869         if (csym.owner.kind != PCK) {
 870             seen.add(csym);
 871         }
 872         if (csym.members() != null) {
 873             for (Symbol s : sym.members().getSymbols()) {
 874                 listNested(s, seen);
 875             }
 876         }
 877         if (csym.trans_local != null) {
 878             for (Symbol s : csym.trans_local) {
 879                 listNested(s, seen);
 880             }
 881         }
 882     }
 883 
 884     /** Write "bootstrapMethods" attribute.
 885      */
 886     void writeBootstrapMethods() {
 887         int alenIdx = writeAttr(names.BootstrapMethods);
 888         databuf.appendChar(poolWriter.bootstrapMethods.size());
 889         for (BsmKey bsmKey : poolWriter.bootstrapMethods.keySet()) {

 890             //write BSM handle
 891             databuf.appendChar(poolWriter.putConstant(bsmKey.bsm));
 892             LoadableConstant[] uniqueArgs = bsmKey.staticArgs;
 893             //write static args length
 894             databuf.appendChar(uniqueArgs.length);
 895             //write static args array
 896             for (LoadableConstant arg : uniqueArgs) {
 897                 databuf.appendChar(poolWriter.putConstant(arg));
 898             }
 899         }
 900         endAttr(alenIdx);
 901     }
 902 
 903     /** Write field symbol, entering all references into constant pool.
 904      */
 905     void writeField(VarSymbol v) {
 906         int flags = adjustFlags(v.flags());
 907         databuf.appendChar(flags);
 908         if (dumpFieldModifiers) {
 909             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 910             pw.println("FIELD  " + v.name);
 911             pw.println("---" + flagNames(v.flags()));
 912         }
 913         databuf.appendChar(poolWriter.putName(v.name));
 914         databuf.appendChar(poolWriter.putDescriptor(v));
 915         int acountIdx = beginAttrs();
 916         int acount = 0;
 917         if (v.getConstValue() != null) {
 918             int alenIdx = writeAttr(names.ConstantValue);
 919             databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
 920             endAttr(alenIdx);
 921             acount++;
 922         }
 923         acount += writeMemberAttrs(v);
 924         endAttrs(acountIdx, acount);
 925     }
 926 
 927     /** Write method symbol, entering all references into constant pool.
 928      */
 929     void writeMethod(MethodSymbol m) {
 930         int flags = adjustFlags(m.flags());
 931         databuf.appendChar(flags);
 932         if (dumpMethodModifiers) {
 933             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 934             pw.println("METHOD  " + m.name);
 935             pw.println("---" + flagNames(m.flags()));
 936         }
 937         databuf.appendChar(poolWriter.putName(m.name));
 938         databuf.appendChar(poolWriter.putDescriptor(m));
 939         int acountIdx = beginAttrs();
 940         int acount = 0;
 941         if (m.code != null) {
 942             int alenIdx = writeAttr(names.Code);
 943             writeCode(m.code);
 944             m.code = null; // to conserve space
 945             endAttr(alenIdx);
 946             acount++;
 947         }
 948         List<Type> thrown = m.erasure(types).getThrownTypes();
 949         if (thrown.nonEmpty()) {
 950             int alenIdx = writeAttr(names.Exceptions);
 951             databuf.appendChar(thrown.length());
 952             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
 953                 databuf.appendChar(poolWriter.putClass(l.head));
 954             endAttr(alenIdx);
 955             acount++;
 956         }
 957         if (m.defaultValue != null) {
 958             int alenIdx = writeAttr(names.AnnotationDefault);
 959             m.defaultValue.accept(awriter);
 960             endAttr(alenIdx);
 961             acount++;
 962         }
 963         if (options.isSet(PARAMETERS) && target.hasMethodParameters()) {
 964             if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
 965                 acount += writeMethodParametersAttr(m);
 966         }
 967         acount += writeMemberAttrs(m);
 968         if (!m.isLambdaMethod())
 969             acount += writeParameterAttrs(m);
 970         endAttrs(acountIdx, acount);
 971     }
 972 
 973     /** Write code attribute of method.


1009             acount++;
1010         }
1011 
1012         // counter for number of generic local variables
1013         if (code.varDebugInfo && code.varBufferSize > 0) {
1014             int nGenericVars = 0;
1015             int alenIdx = writeAttr(names.LocalVariableTable);
1016             databuf.appendChar(code.getLVTSize());
1017             for (int i=0; i<code.varBufferSize; i++) {
1018                 Code.LocalVar var = code.varBuffer[i];
1019 
1020                 for (Code.LocalVar.Range r: var.aliveRanges) {
1021                     // write variable info
1022                     Assert.check(r.start_pc >= 0
1023                             && r.start_pc <= code.cp);
1024                     databuf.appendChar(r.start_pc);
1025                     Assert.check(r.length > 0
1026                             && (r.start_pc + r.length) <= code.cp);
1027                     databuf.appendChar(r.length);
1028                     VarSymbol sym = var.sym;
1029                     databuf.appendChar(poolWriter.putName(sym.name));
1030                     databuf.appendChar(poolWriter.putDescriptor(sym));

1031                     databuf.appendChar(var.reg);
1032                     if (needsLocalVariableTypeEntry(var.sym.type)) {
1033                         nGenericVars++;
1034                     }
1035                 }
1036             }
1037             endAttr(alenIdx);
1038             acount++;
1039 
1040             if (nGenericVars > 0) {
1041                 alenIdx = writeAttr(names.LocalVariableTypeTable);
1042                 databuf.appendChar(nGenericVars);
1043                 int count = 0;
1044 
1045                 for (int i=0; i<code.varBufferSize; i++) {
1046                     Code.LocalVar var = code.varBuffer[i];
1047                     VarSymbol sym = var.sym;
1048                     if (!needsLocalVariableTypeEntry(sym.type))
1049                         continue;
1050                     for (Code.LocalVar.Range r : var.aliveRanges) {
1051                         // write variable info
1052                         databuf.appendChar(r.start_pc);
1053                         databuf.appendChar(r.length);
1054                         databuf.appendChar(poolWriter.putName(sym.name));
1055                         databuf.appendChar(poolWriter.putSignature(sym));
1056                         databuf.appendChar(var.reg);
1057                         count++;
1058                     }
1059                 }
1060                 Assert.check(count == nGenericVars);
1061                 endAttr(alenIdx);
1062                 acount++;
1063             }
1064         }
1065 
1066         if (code.stackMapBufferSize > 0) {
1067             if (debugstackmap) System.out.println("Stack map for " + code.meth);
1068             int alenIdx = writeAttr(code.stackMap.getAttributeName(names));
1069             writeStackMap(code);
1070             endAttr(alenIdx);
1071             acount++;
1072         }
1073 
1074         acount += writeTypeAnnotations(code.meth.getRawTypeAttributes(), true);
1075 


1162                 databuf.appendByte(1);
1163                 break;
1164             case FLOAT:
1165                 if (debugstackmap) System.out.print("float");
1166                 databuf.appendByte(2);
1167                 break;
1168             case DOUBLE:
1169                 if (debugstackmap) System.out.print("double");
1170                 databuf.appendByte(3);
1171                 break;
1172             case LONG:
1173                 if (debugstackmap) System.out.print("long");
1174                 databuf.appendByte(4);
1175                 break;
1176             case BOT: // null
1177                 if (debugstackmap) System.out.print("null");
1178                 databuf.appendByte(5);
1179                 break;
1180             case CLASS:
1181             case ARRAY:




1182             case TYPEVAR:
1183                 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1184                 databuf.appendByte(7);
1185                 databuf.appendChar(poolWriter.putClass(types.erasure(t)));
1186                 break;
1187             case UNINITIALIZED_THIS:
1188                 if (debugstackmap) System.out.print("uninit_this");
1189                 databuf.appendByte(6);
1190                 break;
1191             case UNINITIALIZED_OBJECT:
1192                 { UninitializedType uninitType = (UninitializedType)t;
1193                 databuf.appendByte(8);
1194                 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1195                 databuf.appendChar(uninitType.offset);
1196                 }
1197                 break;
1198             default:
1199                 throw new AssertionError();
1200             }
1201         }
1202 
1203     /** An entry in the JSR202 StackMapTable */
1204     abstract static class StackMapTableFrame {
1205         abstract int getFrameType();


1464         } catch (InvalidSignatureException ex) {
1465             log.error(Errors.CannotGenerateClass(c, Fragments.IllegalSignature(c, ex.type())));
1466         } finally {
1467             if (out != null) {
1468                 // if we are propagating an exception, delete the file
1469                 out.close();
1470                 outFile.delete();
1471                 outFile = null;
1472             }
1473         }
1474         return outFile; // may be null if write failed
1475     }
1476 
1477     /** Write class `c' to outstream `out'.
1478      */
1479     public void writeClassFile(OutputStream out, ClassSymbol c)
1480         throws IOException, PoolOverflow, StringOverflow {
1481         Assert.check((c.flags() & COMPOUND) == 0);
1482         databuf.reset();
1483         poolbuf.reset();





1484 
1485         Type supertype = types.supertype(c.type);
1486         List<Type> interfaces = types.interfaces(c.type);
1487         List<Type> typarams = c.type.getTypeArguments();
1488 
1489         int flags;
1490         if (c.owner.kind == MDL) {
1491             flags = ACC_MODULE;
1492         } else {
1493             flags = adjustFlags(c.flags() & ~DEFAULT);
1494             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1495             flags = flags & ClassFlags & ~STRICTFP;
1496             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
1497         }
1498 
1499         if (dumpClassModifiers) {
1500             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1501             pw.println();
1502             pw.println("CLASSFILE  " + c.getQualifiedName());
1503             pw.println("---" + flagNames(flags));
1504         }
1505         databuf.appendChar(flags);
1506 
1507         if (c.owner.kind == MDL) {
1508             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1509             databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1510         } else {
1511             databuf.appendChar(poolWriter.putClass(c));
1512         }
1513         databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1514         databuf.appendChar(interfaces.length());
1515         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1516             databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
1517         int fieldsCount = 0;
1518         int methodsCount = 0;
1519         for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
1520             switch (sym.kind) {
1521             case VAR: fieldsCount++; break;
1522             case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
1523                       break;
1524             case TYP: poolWriter.enterInner((ClassSymbol)sym); break;
1525             default : Assert.error();
1526             }
1527         }
1528 
1529         if (c.trans_local != null) {
1530             for (ClassSymbol local : c.trans_local) {
1531                 poolWriter.enterInner(local);
1532             }
1533         }
1534 
1535         databuf.appendChar(fieldsCount);
1536         writeFields(c.members());
1537         databuf.appendChar(methodsCount);
1538         writeMethods(c.members());
1539 
1540         int acountIdx = beginAttrs();
1541         int acount = 0;
1542 
1543         boolean sigReq =
1544             typarams.length() != 0 || supertype.allparams().length() != 0;
1545         for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1546             sigReq = l.head.allparams().length() != 0;
1547         if (sigReq) {
1548             int alenIdx = writeAttr(names.Signature);
1549             databuf.appendChar(poolWriter.putSignature(c));





1550             endAttr(alenIdx);
1551             acount++;
1552         }
1553 
1554         if (c.sourcefile != null && emitSourceFile) {
1555             int alenIdx = writeAttr(names.SourceFile);
1556             // WHM 6/29/1999: Strip file path prefix.  We do it here at
1557             // the last possible moment because the sourcefile may be used
1558             // elsewhere in error diagnostics. Fixes 4241573.

1559             String simpleName = PathFileObject.getSimpleName(c.sourcefile);
1560             databuf.appendChar(poolWriter.putName(names.fromString(simpleName)));
1561             endAttr(alenIdx);
1562             acount++;
1563         }
1564 
1565         if (genCrt) {
1566             // Append SourceID attribute
1567             int alenIdx = writeAttr(names.SourceID);
1568             databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
1569             endAttr(alenIdx);
1570             acount++;
1571             // Append CompilationID attribute
1572             alenIdx = writeAttr(names.CompilationID);
1573             databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(System.currentTimeMillis()))));
1574             endAttr(alenIdx);
1575             acount++;
1576         }
1577 
1578         acount += writeFlagAttrs(c.flags());
1579         acount += writeJavaAnnotations(c.getRawAttributes());
1580         acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
1581         acount += writeEnclosingMethodAttribute(c);
1582         if (c.owner.kind == MDL) {
1583             acount += writeModuleAttribute(c);
1584             acount += writeFlagAttrs(c.owner.flags() & ~DEPRECATED);
1585         }
1586         acount += writeExtraClassAttributes(c);
1587 
1588         poolbuf.appendInt(JAVA_MAGIC);
1589         if (preview.isEnabled()) {
1590             poolbuf.appendChar(ClassFile.PREVIEW_MINOR_VERSION);
1591         } else {
1592             poolbuf.appendChar(target.minorVersion);
1593         }
1594         poolbuf.appendChar(target.majorVersion);
1595 
1596         if (c.owner.kind != MDL) {
1597             if (target.hasNestmateAccess()) {
1598                 acount += writeNestMembersIfNeeded(c);
1599                 acount += writeNestHostIfNeeded(c);
1600             }
1601         }
1602 
1603         if (!poolWriter.bootstrapMethods.isEmpty()) {
1604             writeBootstrapMethods();


1605             acount++;
1606         }
1607 
1608         if (!poolWriter.innerClasses.isEmpty()) {
1609             writeInnerClasses();
1610             acount++;
1611         }
1612 
1613         endAttrs(acountIdx, acount);
1614 

1615         out.write(poolbuf.elems, 0, poolbuf.length);
1616 
1617         poolWriter.writePool(out);
1618         poolWriter.reset(); // to save space
1619 
1620         out.write(databuf.elems, 0, databuf.length);
1621      }
1622 
1623     /**Allows subclasses to write additional class attributes
1624      *
1625      * @return the number of attributes written
1626      */
1627     protected int writeExtraClassAttributes(ClassSymbol c) {
1628         return 0;
1629     }
1630 
1631     int adjustFlags(final long flags) {
1632         int result = (int)flags;
1633 
1634         if ((flags & BRIDGE) != 0)
1635             result |= ACC_BRIDGE;
1636         if ((flags & VARARGS) != 0)
1637             result |= ACC_VARARGS;
1638         if ((flags & DEFAULT) != 0)
1639             result &= ~ABSTRACT;
1640         return result;
   1 /*
   2  * Copyright (c) 1999, 2018, 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 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.HashSet;
  33 import java.util.LinkedHashSet;
  34 import java.util.stream.Collectors;
  35 
  36 import javax.tools.JavaFileManager;
  37 import javax.tools.FileObject;
  38 import javax.tools.JavaFileManager.Location;
  39 import javax.tools.JavaFileObject;
  40 
  41 import com.sun.tools.javac.code.*;
  42 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  43 import com.sun.tools.javac.code.Directive.*;
  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.code.Types.UniqueType;
  48 import com.sun.tools.javac.comp.Check;
  49 import com.sun.tools.javac.file.PathFileObject;
  50 import com.sun.tools.javac.jvm.Pool.DynamicMethod;
  51 import com.sun.tools.javac.jvm.Pool.Method;
  52 import com.sun.tools.javac.jvm.Pool.MethodHandle;
  53 import com.sun.tools.javac.jvm.Pool.Variable;
  54 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  55 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  56 import com.sun.tools.javac.util.*;
  57 
  58 import static com.sun.tools.javac.code.Flags.*;
  59 import static com.sun.tools.javac.code.Kinds.Kind.*;
  60 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  61 import static com.sun.tools.javac.code.TypeTag.*;
  62 import static com.sun.tools.javac.main.Option.*;
  63 
  64 import static javax.tools.StandardLocation.CLASS_OUTPUT;
  65 
  66 /** This class provides operations to map an internal symbol table graph
  67  *  rooted in a ClassSymbol into a classfile.
  68  *
  69  *  <p><b>This is NOT part of any supported API.
  70  *  If you write code that depends on this, you do so at your own risk.
  71  *  This code and its internal interfaces are subject to change or
  72  *  deletion without notice.</b>
  73  */


 104     /**
 105      * Source language version.
 106      */
 107     private Source source;
 108 
 109     /** Type utilities. */
 110     private Types types;
 111 
 112     private Check check;
 113 
 114     /**
 115      * If true, class files will be written in module-specific subdirectories
 116      * of the CLASS_OUTPUT location.
 117      */
 118     public boolean multiModuleMode;
 119 
 120     /** The initial sizes of the data and constant pool buffers.
 121      *  Sizes are increased when buffers get full.
 122      */
 123     static final int DATA_BUF_SIZE = 0x0fff0;
 124     static final int POOL_BUF_SIZE = 0x1fff0;
 125 
 126     /** An output buffer for member info.
 127      */
 128     ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
 129 
 130     /** An output buffer for the constant pool.
 131      */
 132     ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
 133 
 134     /** The constant pool.
 135      */
 136     Pool pool;
 137 
 138     /** The inner classes to be written, as a set.
 139      */
 140     Set<ClassSymbol> innerClasses;
 141 
 142     /** The inner classes to be written, as a queue where
 143      *  enclosing classes come first.
 144      */
 145     ListBuffer<ClassSymbol> innerClassesQueue;
 146 
 147     /** The bootstrap methods to be written in the corresponding class attribute
 148      *  (one for each invokedynamic)
 149      */
 150     Map<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> bootstrapMethods;
 151 
 152     /** The log to use for verbose output.
 153      */
 154     private final Log log;
 155 
 156     /** The name table. */
 157     private final Names names;
 158 
 159     /** The symbol table. */
 160     private final Symtab syms;
 161 
 162     /** Access to files. */
 163     private final JavaFileManager fileManager;
 164 
 165     /** Sole signature generator */
 166     private final CWSignatureGenerator signatureGen;
 167 
 168     private final Constables constables;
 169 
 170     /** The tags and constants used in compressed stackmap. */
 171     static final int SAME_FRAME_SIZE = 64;
 172     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 173     static final int SAME_FRAME_EXTENDED = 251;
 174     static final int FULL_FRAME = 255;
 175     static final int MAX_LOCAL_LENGTH_DIFF = 4;
 176 
 177     /** Get the ClassWriter instance for this context. */
 178     public static ClassWriter instance(Context context) {
 179         ClassWriter instance = context.get(classWriterKey);
 180         if (instance == null)
 181             instance = new ClassWriter(context);
 182         return instance;
 183     }
 184 
 185     /** Construct a class writer, given an options table.
 186      */
 187     protected ClassWriter(Context context) {
 188         context.put(classWriterKey, this);
 189 
 190         log = Log.instance(context);
 191         names = Names.instance(context);
 192         syms = Symtab.instance(context);
 193         options = Options.instance(context);
 194         preview = Preview.instance(context);
 195         target = Target.instance(context);
 196         source = Source.instance(context);
 197         types = Types.instance(context);
 198         check = Check.instance(context);
 199         fileManager = context.get(JavaFileManager.class);
 200         signatureGen = new CWSignatureGenerator(types);
 201         constables = Constables.instance(context);
 202 
 203         verbose        = options.isSet(VERBOSE);
 204         genCrt         = options.isSet(XJCOV);
 205         debugstackmap = options.isSet("debug.stackmap");
 206 
 207         emitSourceFile = options.isUnset(G_CUSTOM) ||
 208                             options.isSet(G_CUSTOM, "source");
 209 
 210         String modifierFlags = options.get("debug.dumpmodifiers");
 211         if (modifierFlags != null) {
 212             dumpClassModifiers = modifierFlags.indexOf('c') != -1;
 213             dumpFieldModifiers = modifierFlags.indexOf('f') != -1;
 214             dumpInnerClassModifiers = modifierFlags.indexOf('i') != -1;
 215             dumpMethodModifiers = modifierFlags.indexOf('m') != -1;
 216         }
 217     }
 218 
 219 /******************************************************************
 220  * Diagnostics: dump generated class names and modifiers
 221  ******************************************************************/


 262  ******************************************************************/
 263 
 264     /** Write a character into given byte buffer;
 265      *  byte buffer will not be grown.
 266      */
 267     void putChar(ByteBuffer buf, int op, int x) {
 268         buf.elems[op  ] = (byte)((x >>  8) & 0xFF);
 269         buf.elems[op+1] = (byte)((x      ) & 0xFF);
 270     }
 271 
 272     /** Write an integer into given byte buffer;
 273      *  byte buffer will not be grown.
 274      */
 275     void putInt(ByteBuffer buf, int adr, int x) {
 276         buf.elems[adr  ] = (byte)((x >> 24) & 0xFF);
 277         buf.elems[adr+1] = (byte)((x >> 16) & 0xFF);
 278         buf.elems[adr+2] = (byte)((x >>  8) & 0xFF);
 279         buf.elems[adr+3] = (byte)((x      ) & 0xFF);
 280     }
 281 
 282     /**
 283      * Signature Generation
 284      */
 285     private class CWSignatureGenerator extends Types.SignatureGenerator {
 286 
 287         /**
 288          * An output buffer for type signatures.
 289          */
 290         ByteBuffer sigbuf = new ByteBuffer();
 291 
 292         CWSignatureGenerator(Types types) {
 293             super(types);
 294         }
 295 
 296         /**
 297          * Assemble signature of given type in string buffer.
 298          * Check for uninitialized types before calling the general case.
 299          */
 300         @Override
 301         public void assembleSig(Type type) {
 302             switch (type.getTag()) {
 303                 case UNINITIALIZED_THIS:
 304                 case UNINITIALIZED_OBJECT:
 305                     // we don't yet have a spec for uninitialized types in the
 306                     // local variable table
 307                     assembleSig(types.erasure(((UninitializedType)type).qtype));
 308                     break;
 309                 default:
 310                     super.assembleSig(type);
 311             }
 312         }
 313 
 314         @Override
 315         protected void append(char ch) {
 316             sigbuf.appendByte(ch);
 317         }
 318 
 319         @Override
 320         protected void append(byte[] ba) {
 321             sigbuf.appendBytes(ba);
 322         }
 323 
 324         @Override
 325         protected void append(Name name) {
 326             sigbuf.appendName(name);
 327         }
 328 
 329         @Override
 330         protected void classReference(ClassSymbol c) {
 331             enterInner(c);
 332         }
 333 
 334         private void reset() {
 335             sigbuf.reset();
 336         }
 337 
 338         private Name toName() {
 339             return sigbuf.toName(names);
 340         }
 341 
 342         private boolean isEmpty() {
 343             return sigbuf.length == 0;
 344         }
 345     }
 346 
 347     /**
 348      * Return signature of given type
 349      */
 350     Name typeSig(Type type) {
 351         Assert.check(signatureGen.isEmpty());
 352         //- System.out.println(" ? " + type);
 353         signatureGen.assembleSig(type);
 354         Name n = signatureGen.toName();
 355         signatureGen.reset();
 356         //- System.out.println("   " + n);
 357         return n;
 358     }
 359 
 360     /** Given a type t, return the extended class name of its erasure in
 361      *  external representation.
 362      */
 363     public Name xClassName(Type t) {
 364         if (t.hasTag(CLASS)) {
 365             return names.fromUtf(externalize(t.tsym.flatName()));
 366         } else if (t.hasTag(ARRAY)) {
 367             return typeSig(types.erasure(t));
 368         } else {
 369             throw new AssertionError("xClassName expects class or array type, got " + t);
 370         }
 371     }
 372 
 373 /******************************************************************
 374  * Writing the Constant Pool
 375  ******************************************************************/
 376 
 377     /** Thrown when the constant pool is over full.
 378      */
 379     public static class PoolOverflow extends Exception {
 380         private static final long serialVersionUID = 0;
 381         public PoolOverflow() {}
 382     }
 383     public static class StringOverflow extends Exception {
 384         private static final long serialVersionUID = 0;
 385         public final String value;
 386         public StringOverflow(String s) {
 387             value = s;
 388         }
 389     }
 390 
 391     /** Write constant pool to pool buffer.
 392      *  Note: during writing, constant pool
 393      *  might grow since some parts of constants still need to be entered.
 394      */
 395     void writePool(Pool pool) throws PoolOverflow, StringOverflow {
 396         int poolCountIdx = poolbuf.length;
 397         poolbuf.appendChar(0);
 398         int i = 1;
 399         while (i < pool.pp) {
 400             Object value = pool.pool[i];
 401             Assert.checkNonNull(value);
 402             if (value instanceof Method || value instanceof Variable)
 403                 value = ((DelegatedSymbol)value).getUnderlyingSymbol();
 404 
 405             if (value instanceof MethodSymbol) {
 406                 MethodSymbol m = (MethodSymbol)value;
 407                 if (!m.isDynamic()) {
 408                     poolbuf.appendByte(m.isOwnerAnInterface()
 409                               ? CONSTANT_InterfaceMethodref
 410                               : CONSTANT_Methodref);
 411                     poolbuf.appendChar(pool.put(m.owner));
 412                     poolbuf.appendChar(pool.put(nameType(m)));
 413                 } else {
 414                     //invokedynamic
 415                     DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
 416                     MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
 417                     DynamicMethod.BootstrapMethodsValue val = writeDynSymbol(dynSym, handle);
 418                     poolbuf.appendByte(CONSTANT_InvokeDynamic);
 419                     poolbuf.appendChar(val.index);
 420                     poolbuf.appendChar(pool.put(nameType(dynSym)));
 421                 }
 422             } else if (value instanceof VarSymbol) {
 423                 VarSymbol v = (VarSymbol)value;
 424                 if (!v.isDynamic()) {
 425                     poolbuf.appendByte(CONSTANT_Fieldref);
 426                     poolbuf.appendChar(pool.put(v.owner));
 427                     poolbuf.appendChar(pool.put(nameType(v)));
 428                 } else {
 429                     DynamicVarSymbol dynVarSym = (DynamicVarSymbol)v;
 430                     MethodHandle handle = new MethodHandle(dynVarSym.bsmKind, dynVarSym.bsm, types);
 431                     DynamicMethodSymbol dynSym = new DynamicMethodSymbol(
 432                             handle.refSym.name,
 433                             syms.noSymbol,
 434                             handle.refKind,
 435                             (MethodSymbol)handle.refSym,
 436                             handle.refSym.type,
 437                             dynVarSym.staticArgs);
 438                     DynamicMethod.BootstrapMethodsValue val = writeDynSymbol(dynSym, handle);
 439                     poolbuf.appendByte(CONSTANT_Dynamic);
 440                     poolbuf.appendChar(val.index);
 441                     NameAndType nt = new NameAndType(dynVarSym.name, dynVarSym.type, types);
 442                     poolbuf.appendChar(pool.put(nt));
 443                 }
 444             } else if (value instanceof Name) {
 445                 poolbuf.appendByte(CONSTANT_Utf8);
 446                 byte[] bs = ((Name)value).toUtf();
 447                 poolbuf.appendChar(bs.length);
 448                 poolbuf.appendBytes(bs, 0, bs.length);
 449                 if (bs.length > Pool.MAX_STRING_LENGTH)
 450                     throw new StringOverflow(value.toString());
 451             } else if (value instanceof ClassSymbol) {
 452                 ClassSymbol c = (ClassSymbol)value;
 453                 if (c.owner.kind == TYP) pool.put(c.owner);
 454                 poolbuf.appendByte(CONSTANT_Class);
 455                 if (c.type.hasTag(ARRAY)) {
 456                     poolbuf.appendChar(pool.put(typeSig(c.type)));
 457                 } else {
 458                     poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname))));
 459                     enterInner(c);
 460                 }
 461             } else if (value instanceof NameAndType) {
 462                 NameAndType nt = (NameAndType)value;
 463                 poolbuf.appendByte(CONSTANT_NameandType);
 464                 poolbuf.appendChar(pool.put(nt.name));
 465                 poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
 466             } else if (value instanceof Integer) {
 467                 poolbuf.appendByte(CONSTANT_Integer);
 468                 poolbuf.appendInt(((Integer)value).intValue());
 469             } else if (value instanceof Long) {
 470                 poolbuf.appendByte(CONSTANT_Long);
 471                 poolbuf.appendLong(((Long)value).longValue());
 472                 i++;
 473             } else if (value instanceof Float) {
 474                 poolbuf.appendByte(CONSTANT_Float);
 475                 poolbuf.appendFloat(((Float)value).floatValue());
 476             } else if (value instanceof Double) {
 477                 poolbuf.appendByte(CONSTANT_Double);
 478                 poolbuf.appendDouble(((Double)value).doubleValue());
 479                 i++;
 480             } else if (value instanceof String) {
 481                 poolbuf.appendByte(CONSTANT_String);
 482                 poolbuf.appendChar(pool.put(names.fromString((String)value)));
 483             } else if (value instanceof UniqueType) {
 484                 Type type = ((UniqueType)value).type;
 485                 if (type.hasTag(METHOD)) {
 486                     poolbuf.appendByte(CONSTANT_MethodType);
 487                     poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
 488                 } else {
 489                     Assert.check(type.hasTag(ARRAY));
 490                     poolbuf.appendByte(CONSTANT_Class);
 491                     poolbuf.appendChar(pool.put(xClassName(type)));
 492                 }
 493             } else if (value instanceof MethodHandle) {
 494                 MethodHandle ref = (MethodHandle)value;
 495                 poolbuf.appendByte(CONSTANT_MethodHandle);
 496                 poolbuf.appendByte(ref.refKind);
 497                 poolbuf.appendChar(pool.put(ref.refSym));
 498             } else if (value instanceof ModuleSymbol) {
 499                 ModuleSymbol m = (ModuleSymbol)value;
 500                 poolbuf.appendByte(CONSTANT_Module);
 501                 poolbuf.appendChar(pool.put(m.name));
 502             } else if (value instanceof PackageSymbol) {
 503                 PackageSymbol m = (PackageSymbol)value;
 504                 poolbuf.appendByte(CONSTANT_Package);
 505                 poolbuf.appendChar(pool.put(names.fromUtf(externalize(m.fullname))));
 506             } else {
 507                 Assert.error("writePool " + value);
 508             }
 509             i++;
 510         }
 511         if (pool.pp > Pool.MAX_ENTRIES)
 512             throw new PoolOverflow();
 513         putChar(poolbuf, poolCountIdx, pool.pp);
 514     }
 515 
 516     DynamicMethod.BootstrapMethodsValue writeDynSymbol(DynamicMethodSymbol dynSym, MethodHandle handle) {
 517         DynamicMethod.BootstrapMethodsKey key = new DynamicMethod.BootstrapMethodsKey(dynSym, types);
 518 
 519         // Figure out the index for existing BSM; create a new BSM if no key
 520         DynamicMethod.BootstrapMethodsValue val = bootstrapMethods.get(key);
 521         if (val == null) {
 522             int index = bootstrapMethods.size();
 523             val = new DynamicMethod.BootstrapMethodsValue(handle, index);
 524             bootstrapMethods.put(key, val);
 525         }
 526 
 527         //init cp entries
 528         pool.put(names.BootstrapMethods);
 529         pool.put(handle);
 530         for (Object staticArg : dynSym.staticArgs) {
 531             pool.put(staticArg);
 532         }
 533         return val;
 534     }
 535 
 536     /** Given a symbol, return its name-and-type.
 537      */
 538     NameAndType nameType(Symbol sym) {
 539         return new NameAndType(sym.name, sym.externalType(types), types);
 540         // the NameAndType is generated from a symbol reference, and the
 541         // adjustment of adding an additional this$n parameter needs to be made.
 542     }
 543 
 544 /******************************************************************
 545  * Writing Attributes
 546  ******************************************************************/
 547 
 548     /** Write header for an attribute to data buffer and return
 549      *  position past attribute length index.
 550      */
 551     int writeAttr(Name attrName) {
 552         databuf.appendChar(pool.put(attrName));

 553         databuf.appendInt(0);
 554         return databuf.length;
 555     }
 556 
 557     /** Fill in attribute length.
 558      */
 559     void endAttr(int index) {
 560         putInt(databuf, index - 4, databuf.length - index);
 561     }
 562 
 563     /** Leave space for attribute count and return index for
 564      *  number of attributes field.
 565      */
 566     int beginAttrs() {
 567         databuf.appendChar(0);
 568         return databuf.length;
 569     }
 570 
 571     /** Fill in number of attributes.
 572      */


 578      *  Returns the number of attributes written (0 or 1).
 579      */
 580     int writeEnclosingMethodAttribute(ClassSymbol c) {
 581         return writeEnclosingMethodAttribute(names.EnclosingMethod, c);
 582     }
 583 
 584     /** Write the EnclosingMethod attribute with a specified name.
 585      *  Returns the number of attributes written (0 or 1).
 586      */
 587     protected int writeEnclosingMethodAttribute(Name attributeName, ClassSymbol c) {
 588         if (c.owner.kind != MTH && // neither a local class
 589             c.name != names.empty) // nor anonymous
 590             return 0;
 591 
 592         int alenIdx = writeAttr(attributeName);
 593         ClassSymbol enclClass = c.owner.enclClass();
 594         MethodSymbol enclMethod =
 595             (c.owner.type == null // local to init block
 596              || c.owner.kind != MTH) // or member init
 597             ? null
 598             : (MethodSymbol)c.owner;
 599         databuf.appendChar(pool.put(enclClass));
 600         databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner)));
 601         endAttr(alenIdx);
 602         return 1;
 603     }
 604 
 605     /** Write flag attributes; return number of attributes written.
 606      */
 607     int writeFlagAttrs(long flags) {
 608         int acount = 0;
 609         if ((flags & DEPRECATED) != 0) {
 610             int alenIdx = writeAttr(names.Deprecated);
 611             endAttr(alenIdx);
 612             acount++;
 613         }
 614         return acount;
 615     }
 616 
 617     /** Write member (field or method) attributes;
 618      *  return number of attributes written.
 619      */
 620     int writeMemberAttrs(Symbol sym) {
 621         int acount = writeFlagAttrs(sym.flags());
 622         long flags = sym.flags();
 623         if ((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
 624             (flags & ANONCONSTR) == 0 &&
 625             (!types.isSameType(sym.type, sym.erasure(types)) ||
 626              signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
 627             // note that a local class with captured variables
 628             // will get a signature attribute
 629             int alenIdx = writeAttr(names.Signature);
 630             databuf.appendChar(pool.put(typeSig(sym.type)));
 631             endAttr(alenIdx);
 632             acount++;
 633         }
 634         acount += writeJavaAnnotations(sym.getRawAttributes());
 635         acount += writeTypeAnnotations(sym.getRawTypeAttributes(), false);
 636         return acount;
 637     }
 638 
 639     /**
 640      * Write method parameter names attribute.
 641      */
 642     int writeMethodParametersAttr(MethodSymbol m) {
 643         MethodType ty = m.externalType(types).asMethodType();
 644         final int allparams = ty.argtypes.size();
 645         if (m.params != null && allparams != 0) {
 646             final int attrIndex = writeAttr(names.MethodParameters);
 647             databuf.appendByte(allparams);
 648             // Write extra parameters first
 649             for (VarSymbol s : m.extraParams) {
 650                 final int flags =
 651                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
 652                     ((int) m.flags() & SYNTHETIC);
 653                 databuf.appendChar(pool.put(s.name));
 654                 databuf.appendChar(flags);
 655             }
 656             // Now write the real parameters
 657             for (VarSymbol s : m.params) {
 658                 final int flags =
 659                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
 660                     ((int) m.flags() & SYNTHETIC);
 661                 databuf.appendChar(pool.put(s.name));
 662                 databuf.appendChar(flags);
 663             }
 664             // Now write the captured locals
 665             for (VarSymbol s : m.capturedLocals) {
 666                 final int flags =
 667                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
 668                     ((int) m.flags() & SYNTHETIC);
 669                 databuf.appendChar(pool.put(s.name));
 670                 databuf.appendChar(flags);
 671             }
 672             endAttr(attrIndex);
 673             return 1;
 674         } else
 675             return 0;
 676     }
 677 
 678 
 679     private void writeParamAnnotations(List<VarSymbol> params,
 680                                        RetentionPolicy retention) {
 681         for (VarSymbol s : params) {
 682             ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
 683             for (Attribute.Compound a : s.getRawAttributes())
 684                 if (types.getRetention(a) == retention)
 685                     buf.append(a);
 686             databuf.appendChar(buf.length());
 687             for (Attribute.Compound a : buf)
 688                 writeCompoundAttribute(a);
 689         }


 781             if (tc.hasUnknownPosition()) {
 782                 boolean fixed = tc.tryFixPosition();
 783 
 784                 // Could we fix it?
 785                 if (!fixed) {
 786                     // This happens for nested types like @A Outer. @B Inner.
 787                     // For method parameters we get the annotation twice! Once with
 788                     // a valid position, once unknown.
 789                     // TODO: find a cleaner solution.
 790                     PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 791                     pw.println("ClassWriter: Position UNKNOWN in type annotation: " + tc);
 792                     continue;
 793                 }
 794             }
 795 
 796             if (tc.position.type.isLocal() != inCode)
 797                 continue;
 798             if (!tc.position.emitToClassfile())
 799                 continue;
 800             switch (types.getRetention(tc)) {
 801                 case SOURCE: break;
 802                 case CLASS: invisibles.append(tc); break;
 803                 case RUNTIME: visibles.append(tc); break;
 804                 default: // /* fail soft */ throw new AssertionError(vis);
 805             }
 806         }
 807 
 808         int attrCount = 0;
 809         if (visibles.length() != 0) {
 810             int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations);
 811             databuf.appendChar(visibles.length());
 812             for (Attribute.TypeCompound p : visibles)
 813                 writeTypeAnnotation(p);
 814             endAttr(attrIndex);
 815             attrCount++;
 816         }
 817 
 818         if (invisibles.length() != 0) {
 819             int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations);
 820             databuf.appendChar(invisibles.length());
 821             for (Attribute.TypeCompound p : invisibles)
 822                 writeTypeAnnotation(p);
 823             endAttr(attrIndex);
 824             attrCount++;
 825         }
 826 
 827         return attrCount;
 828     }
 829 
 830     /** A visitor to write an attribute including its leading
 831      *  single-character marker.
 832      */
 833     class AttributeWriter implements Attribute.Visitor {
 834         public void visitConstant(Attribute.Constant _value) {
 835             Object value = _value.value;
 836             switch (_value.type.getTag()) {
 837             case BYTE:
 838                 databuf.appendByte('B');
 839                 break;
 840             case CHAR:
 841                 databuf.appendByte('C');
 842                 break;
 843             case SHORT:
 844                 databuf.appendByte('S');
 845                 break;
 846             case INT:
 847                 databuf.appendByte('I');
 848                 break;
 849             case LONG:
 850                 databuf.appendByte('J');
 851                 break;
 852             case FLOAT:
 853                 databuf.appendByte('F');
 854                 break;
 855             case DOUBLE:
 856                 databuf.appendByte('D');
 857                 break;
 858             case BOOLEAN:
 859                 databuf.appendByte('Z');
 860                 break;
 861             case CLASS:
 862                 Assert.check(value instanceof String);
 863                 databuf.appendByte('s');
 864                 value = names.fromString(value.toString()); // CONSTANT_Utf8
 865                 break;
 866             default:
 867                 throw new AssertionError(_value.type);



























 868             }
 869             databuf.appendChar(pool.put(value));
 870         }
 871         public void visitEnum(Attribute.Enum e) {
 872             databuf.appendByte('e');
 873             databuf.appendChar(pool.put(typeSig(e.value.type)));
 874             databuf.appendChar(pool.put(e.value.name));
 875         }
 876         public void visitClass(Attribute.Class clazz) {
 877             databuf.appendByte('c');
 878             databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType))));
 879         }
 880         public void visitCompound(Attribute.Compound compound) {
 881             databuf.appendByte('@');
 882             writeCompoundAttribute(compound);
 883         }
 884         public void visitError(Attribute.Error x) {
 885             throw new AssertionError(x);
 886         }
 887         public void visitArray(Attribute.Array array) {
 888             databuf.appendByte('[');
 889             databuf.appendChar(array.values.length);
 890             for (Attribute a : array.values) {
 891                 a.accept(this);
 892             }
 893         }
 894     }
 895     AttributeWriter awriter = new AttributeWriter();
 896 
 897     /** Write a compound attribute excluding the '@' marker. */
 898     void writeCompoundAttribute(Attribute.Compound c) {
 899         databuf.appendChar(pool.put(typeSig(c.type)));
 900         databuf.appendChar(c.values.length());
 901         for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
 902             databuf.appendChar(pool.put(p.fst.name));
 903             p.snd.accept(awriter);
 904         }
 905     }
 906 
 907     void writeTypeAnnotation(Attribute.TypeCompound c) {
 908         writePosition(c.position);
 909         writeCompoundAttribute(c);
 910     }
 911 
 912     void writePosition(TypeAnnotationPosition p) {
 913         databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte
 914         switch (p.type) {
 915         // instanceof
 916         case INSTANCEOF:
 917         // new expression
 918         case NEW:
 919         // constructor/method reference receiver
 920         case CONSTRUCTOR_REFERENCE:
 921         case METHOD_REFERENCE:
 922             databuf.appendChar(p.offset);


 986         { // Append location data for generics/arrays.
 987             databuf.appendByte(p.location.size());
 988             java.util.List<Integer> loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location);
 989             for (int i : loc)
 990                 databuf.appendByte((byte)i);
 991         }
 992     }
 993 
 994 /**********************************************************************
 995  * Writing module attributes
 996  **********************************************************************/
 997 
 998     /** Write the Module attribute if needed.
 999      *  Returns the number of attributes written (0 or 1).
1000      */
1001     int writeModuleAttribute(ClassSymbol c) {
1002         ModuleSymbol m = (ModuleSymbol) c.owner;
1003 
1004         int alenIdx = writeAttr(names.Module);
1005 
1006         databuf.appendChar(pool.put(m));
1007         databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
1008         databuf.appendChar(m.version != null ? pool.put(m.version) : 0);
1009 
1010         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
1011         for (RequiresDirective r: m.requires) {
1012             if (!r.flags.contains(RequiresFlag.EXTRA))
1013                 requires.add(r);
1014         }
1015         databuf.appendChar(requires.size());
1016         for (RequiresDirective r: requires) {
1017             databuf.appendChar(pool.put(r.module));
1018             databuf.appendChar(RequiresFlag.value(r.flags));
1019             databuf.appendChar(r.module.version != null ? pool.put(r.module.version) : 0);
1020         }
1021 
1022         List<ExportsDirective> exports = m.exports;
1023         databuf.appendChar(exports.size());
1024         for (ExportsDirective e: exports) {
1025             databuf.appendChar(pool.put(e.packge));
1026             databuf.appendChar(ExportsFlag.value(e.flags));
1027             if (e.modules == null) {
1028                 databuf.appendChar(0);
1029             } else {
1030                 databuf.appendChar(e.modules.size());
1031                 for (ModuleSymbol msym: e.modules) {
1032                     databuf.appendChar(pool.put(msym));
1033                 }
1034             }
1035         }
1036 
1037         List<OpensDirective> opens = m.opens;
1038         databuf.appendChar(opens.size());
1039         for (OpensDirective o: opens) {
1040             databuf.appendChar(pool.put(o.packge));
1041             databuf.appendChar(OpensFlag.value(o.flags));
1042             if (o.modules == null) {
1043                 databuf.appendChar(0);
1044             } else {
1045                 databuf.appendChar(o.modules.size());
1046                 for (ModuleSymbol msym: o.modules) {
1047                     databuf.appendChar(pool.put(msym));
1048                 }
1049             }
1050         }
1051 
1052         List<UsesDirective> uses = m.uses;
1053         databuf.appendChar(uses.size());
1054         for (UsesDirective s: uses) {
1055             databuf.appendChar(pool.put(s.service));
1056         }
1057 
1058         // temporary fix to merge repeated provides clause for same service;
1059         // eventually this should be disallowed when analyzing the module,
1060         // so that each service type only appears once.
1061         Map<ClassSymbol, Set<ClassSymbol>> mergedProvides = new LinkedHashMap<>();
1062         for (ProvidesDirective p : m.provides) {
1063             mergedProvides.computeIfAbsent(p.service, s -> new LinkedHashSet<>()).addAll(p.impls);
1064         }
1065         databuf.appendChar(mergedProvides.size());
1066         mergedProvides.forEach((srvc, impls) -> {
1067             databuf.appendChar(pool.put(srvc));
1068             databuf.appendChar(impls.size());
1069             impls.forEach(impl -> databuf.appendChar(pool.put(impl)));
1070         });
1071 
1072         endAttr(alenIdx);
1073         return 1;
1074     }
1075 
1076 /**********************************************************************
1077  * Writing Objects
1078  **********************************************************************/
1079 
1080     /** Enter an inner class into the `innerClasses' set/queue.
1081      */
1082     void enterInner(ClassSymbol c) {
1083         if (c.type.isCompound()) {
1084             throw new AssertionError("Unexpected intersection type: " + c.type);
1085         }
1086         try {
1087             c.complete();
1088         } catch (CompletionFailure ex) {
1089             System.err.println("warning: " + c + ": " + ex.getMessage());
1090         }
1091         if (!c.type.hasTag(CLASS)) return; // arrays
1092         if (pool != null && // pool might be null if called from xClassName
1093             c.owner.enclClass() != null &&
1094             (innerClasses == null || !innerClasses.contains(c))) {
1095 //          log.errWriter.println("enter inner " + c);//DEBUG
1096             enterInner(c.owner.enclClass());
1097             pool.put(c);
1098             if (c.name != names.empty)
1099                 pool.put(c.name);
1100             if (innerClasses == null) {
1101                 innerClasses = new HashSet<>();
1102                 innerClassesQueue = new ListBuffer<>();
1103                 pool.put(names.InnerClasses);
1104             }
1105             innerClasses.add(c);
1106             innerClassesQueue.append(c);
1107         }
1108     }
1109 
1110     /** Write "inner classes" attribute.
1111      */
1112     void writeInnerClasses() {
1113         int alenIdx = writeAttr(names.InnerClasses);
1114         databuf.appendChar(innerClassesQueue.length());
1115         for (List<ClassSymbol> l = innerClassesQueue.toList();
1116              l.nonEmpty();
1117              l = l.tail) {
1118             ClassSymbol inner = l.head;
1119             inner.markAbstractIfNeeded(types);
1120             char flags = (char) adjustFlags(inner.flags_field);
1121             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
1122             flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.
1123             if (dumpInnerClassModifiers) {
1124                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1125                 pw.println("INNERCLASS  " + inner.name);
1126                 pw.println("---" + flagNames(flags));
1127             }
1128             databuf.appendChar(pool.get(inner));
1129             databuf.appendChar(
1130                 inner.owner.kind == TYP && !inner.name.isEmpty() ? pool.get(inner.owner) : 0);
1131             databuf.appendChar(
1132                 !inner.name.isEmpty() ? pool.get(inner.name) : 0);
1133             databuf.appendChar(flags);
1134         }
1135         endAttr(alenIdx);
1136     }
1137 
1138     /**
1139      * Write NestMembers attribute (if needed)
1140      */
1141     int writeNestMembersIfNeeded(ClassSymbol csym) {
1142         ListBuffer<Symbol> nested = new ListBuffer<>();
1143         listNested(csym, nested);
1144         Set<Symbol> nestedUnique = new LinkedHashSet<>(nested);
1145         if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
1146             int alenIdx = writeAttr(names.NestMembers);
1147             databuf.appendChar(nestedUnique.size());
1148             for (Symbol s : nestedUnique) {
1149                 databuf.appendChar(pool.put(s));
1150             }
1151             endAttr(alenIdx);
1152             return 1;
1153         }
1154         return 0;
1155     }
1156 
1157     /**
1158      * Write NestHost attribute (if needed)
1159      */
1160     int writeNestHostIfNeeded(ClassSymbol csym) {
1161         if (csym.owner.kind != PCK) {
1162             int alenIdx = writeAttr(names.NestHost);
1163             databuf.appendChar(pool.put(csym.outermostClass()));
1164             endAttr(alenIdx);
1165             return 1;
1166         }
1167         return 0;
1168     }
1169 
1170     private void listNested(Symbol sym, ListBuffer<Symbol> seen) {
1171         if (sym.kind != TYP) return;
1172         ClassSymbol csym = (ClassSymbol)sym;
1173         if (csym.owner.kind != PCK) {
1174             seen.add(csym);
1175         }
1176         if (csym.members() != null) {
1177             for (Symbol s : sym.members().getSymbols()) {
1178                 listNested(s, seen);
1179             }
1180         }
1181         if (csym.trans_local != null) {
1182             for (Symbol s : csym.trans_local) {
1183                 listNested(s, seen);
1184             }
1185         }
1186     }
1187 
1188     /** Write "bootstrapMethods" attribute.
1189      */
1190     void writeBootstrapMethods() {
1191         int alenIdx = writeAttr(names.BootstrapMethods);
1192         databuf.appendChar(bootstrapMethods.size());
1193         for (Map.Entry<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> entry : bootstrapMethods.entrySet()) {
1194             DynamicMethod.BootstrapMethodsKey bsmKey = entry.getKey();
1195             //write BSM handle
1196             databuf.appendChar(pool.get(entry.getValue().mh));
1197             Object[] uniqueArgs = bsmKey.getUniqueArgs();
1198             //write static args length
1199             databuf.appendChar(uniqueArgs.length);
1200             //write static args array
1201             for (Object o : uniqueArgs) {
1202                 databuf.appendChar(pool.get(o));
1203             }
1204         }
1205         endAttr(alenIdx);
1206     }
1207 
1208     /** Write field symbol, entering all references into constant pool.
1209      */
1210     void writeField(VarSymbol v) {
1211         int flags = adjustFlags(v.flags());
1212         databuf.appendChar(flags);
1213         if (dumpFieldModifiers) {
1214             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1215             pw.println("FIELD  " + v.name);
1216             pw.println("---" + flagNames(v.flags()));
1217         }
1218         databuf.appendChar(pool.put(v.name));
1219         databuf.appendChar(pool.put(typeSig(v.erasure(types))));
1220         int acountIdx = beginAttrs();
1221         int acount = 0;
1222         if (v.getConstValue() != null && constables.canMakeItToConstantValue(v.type)) {
1223             int alenIdx = writeAttr(names.ConstantValue);
1224             databuf.appendChar(pool.put(v.getConstValue()));
1225             endAttr(alenIdx);
1226             acount++;
1227         }
1228         acount += writeMemberAttrs(v);
1229         endAttrs(acountIdx, acount);
1230     }
1231 
1232     /** Write method symbol, entering all references into constant pool.
1233      */
1234     void writeMethod(MethodSymbol m) {
1235         int flags = adjustFlags(m.flags());
1236         databuf.appendChar(flags);
1237         if (dumpMethodModifiers) {
1238             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1239             pw.println("METHOD  " + m.name);
1240             pw.println("---" + flagNames(m.flags()));
1241         }
1242         databuf.appendChar(pool.put(m.name));
1243         databuf.appendChar(pool.put(typeSig(m.externalType(types))));
1244         int acountIdx = beginAttrs();
1245         int acount = 0;
1246         if (m.code != null) {
1247             int alenIdx = writeAttr(names.Code);
1248             writeCode(m.code);
1249             m.code = null; // to conserve space
1250             endAttr(alenIdx);
1251             acount++;
1252         }
1253         List<Type> thrown = m.erasure(types).getThrownTypes();
1254         if (thrown.nonEmpty()) {
1255             int alenIdx = writeAttr(names.Exceptions);
1256             databuf.appendChar(thrown.length());
1257             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1258                 databuf.appendChar(pool.put(l.head.tsym));
1259             endAttr(alenIdx);
1260             acount++;
1261         }
1262         if (m.defaultValue != null) {
1263             int alenIdx = writeAttr(names.AnnotationDefault);
1264             m.defaultValue.accept(awriter);
1265             endAttr(alenIdx);
1266             acount++;
1267         }
1268         if (options.isSet(PARAMETERS) && target.hasMethodParameters()) {
1269             if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
1270                 acount += writeMethodParametersAttr(m);
1271         }
1272         acount += writeMemberAttrs(m);
1273         if (!m.isLambdaMethod())
1274             acount += writeParameterAttrs(m);
1275         endAttrs(acountIdx, acount);
1276     }
1277 
1278     /** Write code attribute of method.


1314             acount++;
1315         }
1316 
1317         // counter for number of generic local variables
1318         if (code.varDebugInfo && code.varBufferSize > 0) {
1319             int nGenericVars = 0;
1320             int alenIdx = writeAttr(names.LocalVariableTable);
1321             databuf.appendChar(code.getLVTSize());
1322             for (int i=0; i<code.varBufferSize; i++) {
1323                 Code.LocalVar var = code.varBuffer[i];
1324 
1325                 for (Code.LocalVar.Range r: var.aliveRanges) {
1326                     // write variable info
1327                     Assert.check(r.start_pc >= 0
1328                             && r.start_pc <= code.cp);
1329                     databuf.appendChar(r.start_pc);
1330                     Assert.check(r.length > 0
1331                             && (r.start_pc + r.length) <= code.cp);
1332                     databuf.appendChar(r.length);
1333                     VarSymbol sym = var.sym;
1334                     databuf.appendChar(pool.put(sym.name));
1335                     Type vartype = sym.erasure(types);
1336                     databuf.appendChar(pool.put(typeSig(vartype)));
1337                     databuf.appendChar(var.reg);
1338                     if (needsLocalVariableTypeEntry(var.sym.type)) {
1339                         nGenericVars++;
1340                     }
1341                 }
1342             }
1343             endAttr(alenIdx);
1344             acount++;
1345 
1346             if (nGenericVars > 0) {
1347                 alenIdx = writeAttr(names.LocalVariableTypeTable);
1348                 databuf.appendChar(nGenericVars);
1349                 int count = 0;
1350 
1351                 for (int i=0; i<code.varBufferSize; i++) {
1352                     Code.LocalVar var = code.varBuffer[i];
1353                     VarSymbol sym = var.sym;
1354                     if (!needsLocalVariableTypeEntry(sym.type))
1355                         continue;
1356                     for (Code.LocalVar.Range r : var.aliveRanges) {
1357                         // write variable info
1358                         databuf.appendChar(r.start_pc);
1359                         databuf.appendChar(r.length);
1360                         databuf.appendChar(pool.put(sym.name));
1361                         databuf.appendChar(pool.put(typeSig(sym.type)));
1362                         databuf.appendChar(var.reg);
1363                         count++;
1364                     }
1365                 }
1366                 Assert.check(count == nGenericVars);
1367                 endAttr(alenIdx);
1368                 acount++;
1369             }
1370         }
1371 
1372         if (code.stackMapBufferSize > 0) {
1373             if (debugstackmap) System.out.println("Stack map for " + code.meth);
1374             int alenIdx = writeAttr(code.stackMap.getAttributeName(names));
1375             writeStackMap(code);
1376             endAttr(alenIdx);
1377             acount++;
1378         }
1379 
1380         acount += writeTypeAnnotations(code.meth.getRawTypeAttributes(), true);
1381 


1468                 databuf.appendByte(1);
1469                 break;
1470             case FLOAT:
1471                 if (debugstackmap) System.out.print("float");
1472                 databuf.appendByte(2);
1473                 break;
1474             case DOUBLE:
1475                 if (debugstackmap) System.out.print("double");
1476                 databuf.appendByte(3);
1477                 break;
1478             case LONG:
1479                 if (debugstackmap) System.out.print("long");
1480                 databuf.appendByte(4);
1481                 break;
1482             case BOT: // null
1483                 if (debugstackmap) System.out.print("null");
1484                 databuf.appendByte(5);
1485                 break;
1486             case CLASS:
1487             case ARRAY:
1488                 if (debugstackmap) System.out.print("object(" + t + ")");
1489                 databuf.appendByte(7);
1490                 databuf.appendChar(pool.put(t));
1491                 break;
1492             case TYPEVAR:
1493                 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1494                 databuf.appendByte(7);
1495                 databuf.appendChar(pool.put(types.erasure(t).tsym));
1496                 break;
1497             case UNINITIALIZED_THIS:
1498                 if (debugstackmap) System.out.print("uninit_this");
1499                 databuf.appendByte(6);
1500                 break;
1501             case UNINITIALIZED_OBJECT:
1502                 { UninitializedType uninitType = (UninitializedType)t;
1503                 databuf.appendByte(8);
1504                 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1505                 databuf.appendChar(uninitType.offset);
1506                 }
1507                 break;
1508             default:
1509                 throw new AssertionError();
1510             }
1511         }
1512 
1513     /** An entry in the JSR202 StackMapTable */
1514     abstract static class StackMapTableFrame {
1515         abstract int getFrameType();


1774         } catch (InvalidSignatureException ex) {
1775             log.error(Errors.CannotGenerateClass(c, Fragments.IllegalSignature(c, ex.type())));
1776         } finally {
1777             if (out != null) {
1778                 // if we are propagating an exception, delete the file
1779                 out.close();
1780                 outFile.delete();
1781                 outFile = null;
1782             }
1783         }
1784         return outFile; // may be null if write failed
1785     }
1786 
1787     /** Write class `c' to outstream `out'.
1788      */
1789     public void writeClassFile(OutputStream out, ClassSymbol c)
1790         throws IOException, PoolOverflow, StringOverflow {
1791         Assert.check((c.flags() & COMPOUND) == 0);
1792         databuf.reset();
1793         poolbuf.reset();
1794         signatureGen.reset();
1795         pool = c.pool;
1796         innerClasses = null;
1797         innerClassesQueue = null;
1798         bootstrapMethods = new LinkedHashMap<>();
1799 
1800         Type supertype = types.supertype(c.type);
1801         List<Type> interfaces = types.interfaces(c.type);
1802         List<Type> typarams = c.type.getTypeArguments();
1803 
1804         int flags;
1805         if (c.owner.kind == MDL) {
1806             flags = ACC_MODULE;
1807         } else {
1808             flags = adjustFlags(c.flags() & ~DEFAULT);
1809             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1810             flags = flags & ClassFlags & ~STRICTFP;
1811             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
1812         }
1813 
1814         if (dumpClassModifiers) {
1815             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1816             pw.println();
1817             pw.println("CLASSFILE  " + c.getQualifiedName());
1818             pw.println("---" + flagNames(flags));
1819         }
1820         databuf.appendChar(flags);
1821 
1822         if (c.owner.kind == MDL) {
1823             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1824             databuf.appendChar(pool.put(new ClassSymbol(0, names.module_info, unnamed)));
1825         } else {
1826             databuf.appendChar(pool.put(c));
1827         }
1828         databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0);
1829         databuf.appendChar(interfaces.length());
1830         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1831             databuf.appendChar(pool.put(l.head.tsym));
1832         int fieldsCount = 0;
1833         int methodsCount = 0;
1834         for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
1835             switch (sym.kind) {
1836             case VAR: fieldsCount++; break;
1837             case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
1838                       break;
1839             case TYP: enterInner((ClassSymbol)sym); break;
1840             default : Assert.error();
1841             }
1842         }
1843 
1844         if (c.trans_local != null) {
1845             for (ClassSymbol local : c.trans_local) {
1846                 enterInner(local);
1847             }
1848         }
1849 
1850         databuf.appendChar(fieldsCount);
1851         writeFields(c.members());
1852         databuf.appendChar(methodsCount);
1853         writeMethods(c.members());
1854 
1855         int acountIdx = beginAttrs();
1856         int acount = 0;
1857 
1858         boolean sigReq =
1859             typarams.length() != 0 || supertype.allparams().length() != 0;
1860         for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1861             sigReq = l.head.allparams().length() != 0;
1862         if (sigReq) {
1863             int alenIdx = writeAttr(names.Signature);
1864             if (typarams.length() != 0) signatureGen.assembleParamsSig(typarams);
1865             signatureGen.assembleSig(supertype);
1866             for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1867                 signatureGen.assembleSig(l.head);
1868             databuf.appendChar(pool.put(signatureGen.toName()));
1869             signatureGen.reset();
1870             endAttr(alenIdx);
1871             acount++;
1872         }
1873 
1874         if (c.sourcefile != null && emitSourceFile) {
1875             int alenIdx = writeAttr(names.SourceFile);
1876             // WHM 6/29/1999: Strip file path prefix.  We do it here at
1877             // the last possible moment because the sourcefile may be used
1878             // elsewhere in error diagnostics. Fixes 4241573.
1879             //databuf.appendChar(c.pool.put(c.sourcefile));
1880             String simpleName = PathFileObject.getSimpleName(c.sourcefile);
1881             databuf.appendChar(c.pool.put(names.fromString(simpleName)));
1882             endAttr(alenIdx);
1883             acount++;
1884         }
1885 
1886         if (genCrt) {
1887             // Append SourceID attribute
1888             int alenIdx = writeAttr(names.SourceID);
1889             databuf.appendChar(c.pool.put(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
1890             endAttr(alenIdx);
1891             acount++;
1892             // Append CompilationID attribute
1893             alenIdx = writeAttr(names.CompilationID);
1894             databuf.appendChar(c.pool.put(names.fromString(Long.toString(System.currentTimeMillis()))));
1895             endAttr(alenIdx);
1896             acount++;
1897         }
1898 
1899         acount += writeFlagAttrs(c.flags());
1900         acount += writeJavaAnnotations(c.getRawAttributes());
1901         acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
1902         acount += writeEnclosingMethodAttribute(c);
1903         if (c.owner.kind == MDL) {
1904             acount += writeModuleAttribute(c);
1905             acount += writeFlagAttrs(c.owner.flags() & ~DEPRECATED);
1906         }
1907         acount += writeExtraClassAttributes(c);
1908 
1909         poolbuf.appendInt(JAVA_MAGIC);
1910         if (preview.isEnabled()) {
1911             poolbuf.appendChar(ClassFile.PREVIEW_MINOR_VERSION);
1912         } else {
1913             poolbuf.appendChar(target.minorVersion);
1914         }
1915         poolbuf.appendChar(target.majorVersion);
1916 
1917         if (c.owner.kind != MDL) {
1918             if (target.hasNestmateAccess()) {
1919                 acount += writeNestMembersIfNeeded(c);
1920                 acount += writeNestHostIfNeeded(c);
1921             }
1922         }
1923 
1924         writePool(c.pool);
1925 
1926         if (innerClasses != null) {
1927             writeInnerClasses();
1928             acount++;
1929         }
1930 
1931         if (!bootstrapMethods.isEmpty()) {
1932             writeBootstrapMethods();
1933             acount++;
1934         }
1935 
1936         endAttrs(acountIdx, acount);
1937 
1938         poolbuf.appendBytes(databuf.elems, 0, databuf.length);
1939         out.write(poolbuf.elems, 0, poolbuf.length);
1940 
1941         pool = c.pool = null; // to conserve space



1942      }
1943 
1944     /**Allows subclasses to write additional class attributes
1945      *
1946      * @return the number of attributes written
1947      */
1948     protected int writeExtraClassAttributes(ClassSymbol c) {
1949         return 0;
1950     }
1951 
1952     int adjustFlags(final long flags) {
1953         int result = (int)flags;
1954 
1955         if ((flags & BRIDGE) != 0)
1956             result |= ACC_BRIDGE;
1957         if ((flags & VARARGS) != 0)
1958             result |= ACC_VARARGS;
1959         if ((flags & DEFAULT) != 0)
1960             result &= ~ABSTRACT;
1961         return result;
< prev index next >