langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
changeset 15385 ee1eebe7e210
parent 15031 c4fad55a5681
child 15564 6d8db91563a7
equal deleted inserted replaced
15384:5a8d00abf076 15385:ee1eebe7e210
     1 /*
     1 /*
     2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    29 import java.util.LinkedHashMap;
    29 import java.util.LinkedHashMap;
    30 import java.util.Map;
    30 import java.util.Map;
    31 import java.util.Set;
    31 import java.util.Set;
    32 import java.util.HashSet;
    32 import java.util.HashSet;
    33 
    33 
       
    34 import javax.lang.model.type.TypeKind;
    34 import javax.tools.JavaFileManager;
    35 import javax.tools.JavaFileManager;
    35 import javax.tools.FileObject;
    36 import javax.tools.FileObject;
    36 import javax.tools.JavaFileObject;
    37 import javax.tools.JavaFileObject;
    37 
    38 
    38 import com.sun.tools.javac.code.*;
    39 import com.sun.tools.javac.code.*;
    39 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
    40 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
       
    41 import com.sun.tools.javac.code.Attribute.TypeCompound;
    40 import com.sun.tools.javac.code.Symbol.*;
    42 import com.sun.tools.javac.code.Symbol.*;
    41 import com.sun.tools.javac.code.Type.*;
    43 import com.sun.tools.javac.code.Type.*;
    42 import com.sun.tools.javac.code.Types.UniqueType;
    44 import com.sun.tools.javac.code.Types.UniqueType;
    43 import com.sun.tools.javac.file.BaseFileObject;
    45 import com.sun.tools.javac.file.BaseFileObject;
    44 import com.sun.tools.javac.jvm.Pool.DynamicMethod;
    46 import com.sun.tools.javac.jvm.Pool.DynamicMethod;
    45 import com.sun.tools.javac.jvm.Pool.Method;
    47 import com.sun.tools.javac.jvm.Pool.Method;
    46 import com.sun.tools.javac.jvm.Pool.MethodHandle;
    48 import com.sun.tools.javac.jvm.Pool.MethodHandle;
    47 import com.sun.tools.javac.jvm.Pool.Variable;
    49 import com.sun.tools.javac.jvm.Pool.Variable;
    48 import com.sun.tools.javac.util.*;
    50 import com.sun.tools.javac.util.*;
    49 
    51 
    50 import static com.sun.tools.javac.code.BoundKind.*;
       
    51 import static com.sun.tools.javac.code.Flags.*;
    52 import static com.sun.tools.javac.code.Flags.*;
    52 import static com.sun.tools.javac.code.Kinds.*;
    53 import static com.sun.tools.javac.code.Kinds.*;
    53 import static com.sun.tools.javac.code.TypeTag.*;
    54 import static com.sun.tools.javac.code.TypeTag.*;
    54 import static com.sun.tools.javac.jvm.UninitializedType.*;
    55 import static com.sun.tools.javac.jvm.UninitializedType.*;
    55 import static com.sun.tools.javac.main.Option.*;
    56 import static com.sun.tools.javac.main.Option.*;
    66  */
    67  */
    67 public class ClassWriter extends ClassFile {
    68 public class ClassWriter extends ClassFile {
    68     protected static final Context.Key<ClassWriter> classWriterKey =
    69     protected static final Context.Key<ClassWriter> classWriterKey =
    69         new Context.Key<ClassWriter>();
    70         new Context.Key<ClassWriter>();
    70 
    71 
    71     private final Symtab syms;
       
    72 
       
    73     private final Options options;
    72     private final Options options;
    74 
    73 
    75     /** Switch: verbose output.
    74     /** Switch: verbose output.
    76      */
    75      */
    77     private boolean verbose;
    76     private boolean verbose;
    78 
    77 
    79     /** Switch: scramble private names.
    78     /** Switch: scramble private field names.
    80      */
    79      */
    81     private boolean scramble;
    80     private boolean scramble;
    82 
    81 
    83     /** Switch: scramble private names.
    82     /** Switch: scramble all field names.
    84      */
    83      */
    85     private boolean scrambleAll;
    84     private boolean scrambleAll;
    86 
    85 
    87     /** Switch: retrofit mode.
    86     /** Switch: retrofit mode.
    88      */
    87      */
    94 
    93 
    95     /** Switch: generate CharacterRangeTable attribute.
    94     /** Switch: generate CharacterRangeTable attribute.
    96      */
    95      */
    97     private boolean genCrt;
    96     private boolean genCrt;
    98 
    97 
    99     /** Switch: describe the generated stackmap
    98     /** Switch: describe the generated stackmap.
   100      */
    99      */
   101     boolean debugstackmap;
   100     boolean debugstackmap;
   102 
   101 
   103     /**
   102     /**
   104      * Target class version.
   103      * Target class version.
   112 
   111 
   113     /** Type utilities. */
   112     /** Type utilities. */
   114     private Types types;
   113     private Types types;
   115 
   114 
   116     /** The initial sizes of the data and constant pool buffers.
   115     /** The initial sizes of the data and constant pool buffers.
   117      *  sizes are increased when buffers get full.
   116      *  Sizes are increased when buffers get full.
   118      */
   117      */
   119     static final int DATA_BUF_SIZE = 0x0fff0;
   118     static final int DATA_BUF_SIZE = 0x0fff0;
   120     static final int POOL_BUF_SIZE = 0x1fff0;
   119     static final int POOL_BUF_SIZE = 0x1fff0;
   121 
   120 
   122     /** An output buffer for member info.
   121     /** An output buffer for member info.
   179     protected ClassWriter(Context context) {
   178     protected ClassWriter(Context context) {
   180         context.put(classWriterKey, this);
   179         context.put(classWriterKey, this);
   181 
   180 
   182         log = Log.instance(context);
   181         log = Log.instance(context);
   183         names = Names.instance(context);
   182         names = Names.instance(context);
   184         syms = Symtab.instance(context);
       
   185         options = Options.instance(context);
   183         options = Options.instance(context);
   186         target = Target.instance(context);
   184         target = Target.instance(context);
   187         source = Source.instance(context);
   185         source = Source.instance(context);
   188         types = Types.instance(context);
   186         types = Types.instance(context);
   189         fileManager = context.get(JavaFileManager.class);
   187         fileManager = context.get(JavaFileManager.class);
   277  ******************************************************************/
   275  ******************************************************************/
   278 
   276 
   279     /** Assemble signature of given type in string buffer.
   277     /** Assemble signature of given type in string buffer.
   280      */
   278      */
   281     void assembleSig(Type type) {
   279     void assembleSig(Type type) {
       
   280         type = type.unannotatedType();
   282         switch (type.getTag()) {
   281         switch (type.getTag()) {
   283         case BYTE:
   282         case BYTE:
   284             sigbuf.appendByte('B');
   283             sigbuf.appendByte('B');
   285             break;
   284             break;
   286         case SHORT:
   285         case SHORT:
   377         }
   376         }
   378         return false;
   377         return false;
   379     }
   378     }
   380 
   379 
   381     void assembleClassSig(Type type) {
   380     void assembleClassSig(Type type) {
       
   381         type = type.unannotatedType();
   382         ClassType ct = (ClassType)type;
   382         ClassType ct = (ClassType)type;
   383         ClassSymbol c = (ClassSymbol)ct.tsym;
   383         ClassSymbol c = (ClassSymbol)ct.tsym;
   384         enterInner(c);
   384         enterInner(c);
   385         Type outer = ct.getEnclosingType();
   385         Type outer = ct.getEnclosingType();
   386         if (outer.allparams().nonEmpty()) {
   386         if (outer.allparams().nonEmpty()) {
   720             databuf.appendChar(pool.put(typeSig(sym.type)));
   720             databuf.appendChar(pool.put(typeSig(sym.type)));
   721             endAttr(alenIdx);
   721             endAttr(alenIdx);
   722             acount++;
   722             acount++;
   723         }
   723         }
   724         acount += writeJavaAnnotations(sym.getRawAttributes());
   724         acount += writeJavaAnnotations(sym.getRawAttributes());
       
   725         acount += writeTypeAnnotations(sym.getRawTypeAttributes());
   725         return acount;
   726         return acount;
   726     }
   727     }
   727 
   728 
   728     /**
   729     /**
   729      * Write method parameter names attribute.
   730      * Write method parameter names attribute.
   836             attrCount++;
   837             attrCount++;
   837         }
   838         }
   838         return attrCount;
   839         return attrCount;
   839     }
   840     }
   840 
   841 
       
   842     int writeTypeAnnotations(List<Attribute.TypeCompound> typeAnnos) {
       
   843         if (typeAnnos.isEmpty()) return 0;
       
   844 
       
   845         ListBuffer<Attribute.TypeCompound> visibles = ListBuffer.lb();
       
   846         ListBuffer<Attribute.TypeCompound> invisibles = ListBuffer.lb();
       
   847 
       
   848         for (Attribute.TypeCompound tc : typeAnnos) {
       
   849             if (tc.position == null || tc.position.type == TargetType.UNKNOWN) {
       
   850                 boolean found = false;
       
   851                 // TODO: the position for the container annotation of a
       
   852                 // repeating type annotation has to be set.
       
   853                 // This cannot be done when the container is created, because
       
   854                 // then the position is not determined yet.
       
   855                 // How can we link these pieces better together?
       
   856                 if (tc.values.size() == 1) {
       
   857                     Pair<MethodSymbol, Attribute> val = tc.values.get(0);
       
   858                     if (val.fst.getSimpleName().contentEquals("value") &&
       
   859                             val.snd instanceof Attribute.Array) {
       
   860                         Attribute.Array arr = (Attribute.Array) val.snd;
       
   861                         if (arr.values.length != 0 &&
       
   862                                 arr.values[0] instanceof Attribute.TypeCompound) {
       
   863                             TypeCompound atycomp = (Attribute.TypeCompound) arr.values[0];
       
   864                             if (atycomp.position.type != TargetType.UNKNOWN) {
       
   865                                 tc.position = atycomp.position;
       
   866                                 found = true;
       
   867                             }
       
   868                         }
       
   869                     }
       
   870                 }
       
   871                 if (!found) {
       
   872                     // This happens for nested types like @A Outer. @B Inner.
       
   873                     // For method parameters we get the annotation twice! Once with
       
   874                     // a valid position, once unknown.
       
   875                     // TODO: find a cleaner solution.
       
   876                     // System.err.println("ClassWriter: Position UNKNOWN in type annotation: " + tc);
       
   877                     continue;
       
   878                 }
       
   879             }
       
   880             if (!tc.position.emitToClassfile())
       
   881                 continue;
       
   882             switch (types.getRetention(tc)) {
       
   883             case SOURCE: break;
       
   884             case CLASS: invisibles.append(tc); break;
       
   885             case RUNTIME: visibles.append(tc); break;
       
   886             default: ;// /* fail soft */ throw new AssertionError(vis);
       
   887             }
       
   888         }
       
   889 
       
   890         int attrCount = 0;
       
   891         if (visibles.length() != 0) {
       
   892             int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations);
       
   893             databuf.appendChar(visibles.length());
       
   894             for (Attribute.TypeCompound p : visibles)
       
   895                 writeTypeAnnotation(p);
       
   896             endAttr(attrIndex);
       
   897             attrCount++;
       
   898         }
       
   899 
       
   900         if (invisibles.length() != 0) {
       
   901             int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations);
       
   902             databuf.appendChar(invisibles.length());
       
   903             for (Attribute.TypeCompound p : invisibles)
       
   904                 writeTypeAnnotation(p);
       
   905             endAttr(attrIndex);
       
   906             attrCount++;
       
   907         }
       
   908 
       
   909         return attrCount;
       
   910     }
       
   911 
   841     /** A visitor to write an attribute including its leading
   912     /** A visitor to write an attribute including its leading
   842      *  single-character marker.
   913      *  single-character marker.
   843      */
   914      */
   844     class AttributeWriter implements Attribute.Visitor {
   915     class AttributeWriter implements Attribute.Visitor {
   845         public void visitConstant(Attribute.Constant _value) {
   916         public void visitConstant(Attribute.Constant _value) {
   912         for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
   983         for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
   913             databuf.appendChar(pool.put(p.fst.name));
   984             databuf.appendChar(pool.put(p.fst.name));
   914             p.snd.accept(awriter);
   985             p.snd.accept(awriter);
   915         }
   986         }
   916     }
   987     }
       
   988 
       
   989     void writeTypeAnnotation(Attribute.TypeCompound c) {
       
   990         writePosition(c.position);
       
   991         writeCompoundAttribute(c);
       
   992     }
       
   993 
       
   994     void writePosition(TypeAnnotationPosition p) {
       
   995         databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte
       
   996         switch (p.type) {
       
   997         // type cast
       
   998         case CAST:
       
   999         // instanceof
       
  1000         case INSTANCEOF:
       
  1001         // new expression
       
  1002         case NEW:
       
  1003             databuf.appendChar(p.offset);
       
  1004             break;
       
  1005         // local variable
       
  1006         case LOCAL_VARIABLE:
       
  1007         // resource variable
       
  1008         case RESOURCE_VARIABLE:
       
  1009             databuf.appendChar(p.lvarOffset.length);  // for table length
       
  1010             for (int i = 0; i < p.lvarOffset.length; ++i) {
       
  1011                 databuf.appendChar(p.lvarOffset[i]);
       
  1012                 databuf.appendChar(p.lvarLength[i]);
       
  1013                 databuf.appendChar(p.lvarIndex[i]);
       
  1014             }
       
  1015             break;
       
  1016         // exception parameter
       
  1017         case EXCEPTION_PARAMETER:
       
  1018             databuf.appendByte(p.exception_index);
       
  1019             break;
       
  1020         // method receiver
       
  1021         case METHOD_RECEIVER:
       
  1022             // Do nothing
       
  1023             break;
       
  1024         // type parameter
       
  1025         case CLASS_TYPE_PARAMETER:
       
  1026         case METHOD_TYPE_PARAMETER:
       
  1027             databuf.appendByte(p.parameter_index);
       
  1028             break;
       
  1029         // type parameter bound
       
  1030         case CLASS_TYPE_PARAMETER_BOUND:
       
  1031         case METHOD_TYPE_PARAMETER_BOUND:
       
  1032             databuf.appendByte(p.parameter_index);
       
  1033             databuf.appendByte(p.bound_index);
       
  1034             break;
       
  1035         // class extends or implements clause
       
  1036         case CLASS_EXTENDS:
       
  1037             databuf.appendChar(p.type_index);
       
  1038             break;
       
  1039         // throws
       
  1040         case THROWS:
       
  1041             databuf.appendChar(p.type_index);
       
  1042             break;
       
  1043         // method parameter
       
  1044         case METHOD_FORMAL_PARAMETER:
       
  1045             databuf.appendByte(p.parameter_index);
       
  1046             break;
       
  1047         // method/constructor/reference type argument
       
  1048         case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
       
  1049         case METHOD_INVOCATION_TYPE_ARGUMENT:
       
  1050         case METHOD_REFERENCE_TYPE_ARGUMENT:
       
  1051             databuf.appendChar(p.offset);
       
  1052             databuf.appendByte(p.type_index);
       
  1053             break;
       
  1054         // We don't need to worry about these
       
  1055         case METHOD_RETURN:
       
  1056         case FIELD:
       
  1057             break;
       
  1058         // lambda formal parameter
       
  1059         case LAMBDA_FORMAL_PARAMETER:
       
  1060             databuf.appendByte(p.parameter_index);
       
  1061             break;
       
  1062         case UNKNOWN:
       
  1063             throw new AssertionError("jvm.ClassWriter: UNKNOWN target type should never occur!");
       
  1064         default:
       
  1065             throw new AssertionError("jvm.ClassWriter: Unknown target type for position: " + p);
       
  1066         }
       
  1067 
       
  1068         { // Append location data for generics/arrays.
       
  1069             databuf.appendByte(p.location.size());
       
  1070             java.util.List<Integer> loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location);
       
  1071             for (int i : loc)
       
  1072                 databuf.appendByte((byte)i);
       
  1073         }
       
  1074     }
       
  1075 
   917 /**********************************************************************
  1076 /**********************************************************************
   918  * Writing Objects
  1077  * Writing Objects
   919  **********************************************************************/
  1078  **********************************************************************/
   920 
  1079 
   921     /** Enter an inner class into the `innerClasses' set/queue.
  1080     /** Enter an inner class into the `innerClasses' set/queue.
  1659             acount++;
  1818             acount++;
  1660         }
  1819         }
  1661 
  1820 
  1662         acount += writeFlagAttrs(c.flags());
  1821         acount += writeFlagAttrs(c.flags());
  1663         acount += writeJavaAnnotations(c.getRawAttributes());
  1822         acount += writeJavaAnnotations(c.getRawAttributes());
       
  1823         acount += writeTypeAnnotations(c.getRawTypeAttributes());
  1664         acount += writeEnclosingMethodAttribute(c);
  1824         acount += writeEnclosingMethodAttribute(c);
  1665         acount += writeExtraClassAttributes(c);
  1825         acount += writeExtraClassAttributes(c);
  1666 
  1826 
  1667         poolbuf.appendInt(JAVA_MAGIC);
  1827         poolbuf.appendInt(JAVA_MAGIC);
  1668         poolbuf.appendChar(target.minorVersion);
  1828         poolbuf.appendChar(target.minorVersion);