< prev index next >

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

Print this page
*** 42,10 ***
--- 42,11 ---
  import javax.lang.model.element.NestingKind;
  import javax.tools.JavaFileManager;
  import javax.tools.JavaFileObject;
  
  import com.sun.tools.javac.code.Source.Feature;
+ import com.sun.tools.javac.code.Type.ClassType.Flavor;
  import com.sun.tools.javac.comp.Annotate;
  import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
  import com.sun.tools.javac.code.*;
  import com.sun.tools.javac.code.Directive.*;
  import com.sun.tools.javac.code.Lint.LintCategory;

*** 103,10 ***
--- 104,14 ---
  
      /** Switch: allow modules.
       */
      boolean allowModules;
  
+     /** Switch: allow primitive classes.
+      */
+     boolean allowPrimitiveClasses;
+ 
      /** Switch: allow sealed
       */
      boolean allowSealedTypes;
  
      /** Switch: allow records

*** 275,10 ***
--- 280,11 ---
          verbose         = options.isSet(Option.VERBOSE);
  
          Source source = Source.instance(context);
          preview = Preview.instance(context);
          allowModules     = Feature.MODULES.allowedInSource(source);
+         allowPrimitiveClasses = Feature.PRIMITIVE_CLASSES.allowedInSource(source);
          allowRecords = Feature.RECORDS.allowedInSource(source);
          allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
  
          saveParameterNames = options.isSet(PARAMETERS);
  

*** 470,10 ***
--- 476,11 ---
              sigp++;
              return syms.intType;
          case 'J':
              sigp++;
              return syms.longType;
+         case 'Q':
          case 'L':
              {
                  // int oldsigp = sigp;
                  Type t = classSigToType();
                  if (sigp < siglimit && signature[sigp] == '.')

*** 531,15 ***
      byte[] signatureBuffer = new byte[0];
      int sbp = 0;
      /** Convert class signature to type, where signature is implicit.
       */
      Type classSigToType() {
!         if (signature[sigp] != 'L')
              throw badClassFile("bad.class.signature",
                                 Convert.utf2string(signature, sigp, 10));
          sigp++;
          Type outer = Type.noType;
          int startSbp = sbp;
  
          while (true) {
              final byte c = signature[sigp++];
              switch (c) {
--- 538,18 ---
      byte[] signatureBuffer = new byte[0];
      int sbp = 0;
      /** Convert class signature to type, where signature is implicit.
       */
      Type classSigToType() {
!         byte prefix = signature[sigp];
+         if (prefix != 'L' && prefix != 'Q')
              throw badClassFile("bad.class.signature",
                                 Convert.utf2string(signature, sigp, 10));
          sigp++;
          Type outer = Type.noType;
+         Name name;
+         ClassType.Flavor flavor;
          int startSbp = sbp;
  
          while (true) {
              final byte c = signature[sigp++];
              switch (c) {

*** 547,24 ***
              case ';': {         // end
                  ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                           startSbp,
                                                           sbp - startSbp));
  
                  try {
!                     return (outer == Type.noType) ?
!                             t.erasure(types) :
!                         new ClassType(outer, List.nil(), t);
                  } finally {
                      sbp = startSbp;
                  }
              }
  
              case '<':           // generic arguments
                  ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                           startSbp,
                                                           sbp - startSbp));
!                 outer = new ClassType(outer, sigToTypes('>'), t) {
                          boolean completed = false;
                          @Override @DefinedBy(Api.LANGUAGE_MODEL)
                          public Type getEnclosingType() {
                              if (!completed) {
                                  completed = true;
--- 557,31 ---
              case ';': {         // end
                  ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                           startSbp,
                                                           sbp - startSbp));
  
+                 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
+                 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
                  try {
!                     if (outer == Type.noType) {
!                         ClassType et = (ClassType) t.erasure(types);
!                         // Todo: This spews out more objects than before, i.e no reuse with identical flavor
+                         return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata(), flavor);
+                     }
+                     return new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
                  } finally {
                      sbp = startSbp;
                  }
              }
  
              case '<':           // generic arguments
                  ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                           startSbp,
                                                           sbp - startSbp));
!                 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
+                 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
+                 outer = new ClassType(outer, sigToTypes('>'), t, TypeMetadata.EMPTY, flavor) {
                          boolean completed = false;
                          @Override @DefinedBy(Api.LANGUAGE_MODEL)
                          public Type getEnclosingType() {
                              if (!completed) {
                                  completed = true;

*** 623,11 ***
                  //we have seen an enclosing non-generic class
                  if (outer != Type.noType) {
                      t = enterClass(names.fromUtf(signatureBuffer,
                                                   startSbp,
                                                   sbp - startSbp));
!                     outer = new ClassType(outer, List.nil(), t);
                  }
                  signatureBuffer[sbp++] = (byte)'$';
                  continue;
              case '/':
                  signatureBuffer[sbp++] = (byte)'.';
--- 640,13 ---
                  //we have seen an enclosing non-generic class
                  if (outer != Type.noType) {
                      t = enterClass(names.fromUtf(signatureBuffer,
                                                   startSbp,
                                                   sbp - startSbp));
!                     // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
+                     flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
+                     outer = new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
                  }
                  signatureBuffer[sbp++] = (byte)'$';
                  continue;
              case '/':
                  signatureBuffer[sbp++] = (byte)'.';

*** 788,10 ***
--- 807,21 ---
          AttributeReader[] readers = {
              // v45.3 attributes
  
              new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
                  protected void read(Symbol sym, int attrLen) {
+                     if (allowPrimitiveClasses) {
+                         if (sym.isConstructor()  && ((MethodSymbol) sym).type.getParameterTypes().size() == 0) {
+                             int code_length = buf.getInt(bp + 4);
+                             if ((code_length == 1 && buf.getByte( bp + 8) == (byte) ByteCodes.return_) ||
+                                     (code_length == 5 && buf.getByte(bp + 8) == ByteCodes.aload_0 &&
+                                         buf.getByte( bp + 9) == (byte) ByteCodes.invokespecial &&
+                                                 buf.getByte( bp + 12) == (byte) ByteCodes.return_)) {
+                                     sym.flags_field |= EMPTYNOARGCONSTR;
+                             }
+                         }
+                     }
                      if (saveParameterNames)
                          ((MethodSymbol)sym).code = readCode(sym);
                      else
                          bp = bp + attrLen;
                  }

*** 968,10 ***
--- 998,16 ---
                          List<Type> thrown = sym.type.getThrownTypes();
                          sym.type = poolReader.getType(nextChar());
                          //- System.err.println(" # " + sym.type);
                          if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
                              sym.type.asMethodType().thrown = thrown;
+                         if (sym.kind == MTH  && sym.name == names.init && sym.owner.isPrimitiveClass()) {
+                             sym.type = new MethodType(sym.type.getParameterTypes(),
+                                     syms.voidType,
+                                     sym.type.getThrownTypes(),
+                                     syms.methodClass);
+                         }
  
                      }
                  }
              },
  

*** 1238,10 ***
--- 1274,23 ---
                          }
                          ((ClassSymbol)sym).permitted = subtypes.toList();
                      }
                  }
              },
+             new AttributeReader(names.JavaFlags, V61, CLASS_ATTRIBUTE) {
+                 @Override
+                 protected boolean accepts(AttributeKind kind) {
+                     return super.accepts(kind) && allowPrimitiveClasses;
+                 }
+                 protected void read(Symbol sym, int attrLen) {
+                     if (sym.kind == TYP) {
+                         int extendedFlags = nextChar();
+                         if ((extendedFlags & ACC_REF_DEFAULT) != 0)
+                         ((ClassSymbol)sym).flags_field |= REFERENCE_FAVORING;
+                     }
+                 }
+             }
          };
  
          for (AttributeReader r: readers)
              attributeReaders.put(r.name, r);
      }

*** 2226,10 ***
--- 2275,17 ---
                  throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
                                     Integer.toString(majorVersion),
                                     Integer.toString(minorVersion));
              }
          }
+         if (name == names.init && ((flags & STATIC) != 0)) {
+             flags &= ~STATIC;
+             type = new MethodType(type.getParameterTypes(),
+                     syms.voidType,
+                     type.getThrownTypes(),
+                     syms.methodClass);
+         }
          validateMethodType(name, type);
          if (name == names.init && currentOwner.hasOuterInstance()) {
              // Sometimes anonymous classes don't have an outer
              // instance, however, there is no reliable way to tell so
              // we never strip this$n

*** 2738,10 ***
--- 2794,16 ---
      long adjustClassFlags(long flags) {
          if ((flags & ACC_MODULE) != 0) {
              flags &= ~ACC_MODULE;
              flags |= MODULE;
          }
+         if ((flags & ACC_PRIMITIVE) != 0) {
+             flags &= ~ACC_PRIMITIVE;
+             if (allowPrimitiveClasses) {
+                 flags |= PRIMITIVE_CLASS;
+             }
+         }
          return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
      }
  
      /**
       * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
< prev index next >