< prev index next >

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

Print this page
*** 60,13 ***
--- 60,15 ---
  import com.sun.tools.javac.file.BaseFileManager;
  import com.sun.tools.javac.file.PathFileObject;
  import com.sun.tools.javac.jvm.ClassFile.Version;
  import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
  import com.sun.tools.javac.main.Option;
+ import com.sun.tools.javac.resources.CompilerProperties;
  import com.sun.tools.javac.resources.CompilerProperties.Errors;
  import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+ import com.sun.tools.javac.tree.JCTree;
  import com.sun.tools.javac.util.*;
  import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
  import com.sun.tools.javac.util.DefinedBy.Api;
  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  import com.sun.tools.javac.util.JCDiagnostic.Fragment;

*** 74,10 ***
--- 76,11 ---
  import static com.sun.tools.javac.code.Flags.*;
  import static com.sun.tools.javac.code.Kinds.Kind.*;
  
  import com.sun.tools.javac.code.Scope.LookupKind;
  
+ import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  import static com.sun.tools.javac.code.TypeTag.ARRAY;
  import static com.sun.tools.javac.code.TypeTag.CLASS;
  import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
  import static com.sun.tools.javac.jvm.ClassFile.*;
  import static com.sun.tools.javac.jvm.ClassFile.Version.*;

*** 109,10 ***
--- 112,14 ---
  
      /** Switch: allow modules.
       */
      boolean allowModules;
  
+     /** Switch: allow value classes.
+      */
+     boolean allowValueClasses;
+ 
      /** Switch: allow sealed
       */
      boolean allowSealedTypes;
  
      /** Switch: allow records

*** 289,10 ***
--- 296,12 ---
          verbose         = options.isSet(Option.VERBOSE);
  
          Source source = Source.instance(context);
          preview = Preview.instance(context);
          allowModules     = Feature.MODULES.allowedInSource(source);
+         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
+                 Feature.VALUE_CLASSES.allowedInSource(source);
          allowRecords = Feature.RECORDS.allowedInSource(source);
          allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
          warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
  
          saveParameterNames = options.isSet(PARAMETERS);

*** 583,13 ***
                  ClassSymbol t = enterClass(readName(signatureBuffer,
                                                           startSbp,
                                                           sbp - startSbp));
  
                  try {
!                     return (outer == Type.noType) ?
!                             t.erasure(types) :
!                         new ClassType(outer, List.nil(), t);
                  } finally {
                      sbp = startSbp;
                  }
              }
  
--- 592,15 ---
                  ClassSymbol t = enterClass(readName(signatureBuffer,
                                                           startSbp,
                                                           sbp - startSbp));
  
                  try {
!                     if (outer == Type.noType) {
!                         ClassType et = (ClassType) t.erasure(types);
!                         return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
+                     }
+                     return new ClassType(outer, List.nil(), t, List.nil());
                  } finally {
                      sbp = startSbp;
                  }
              }
  

*** 607,11 ***
                   * this additional local variable and depend on field ClassType::typarams_field which `actuals` is
                   * assigned to but then we would have a dependendy on the internal representation of ClassType which
                   * could change in the future
                   */
                  final List<Type> actualsCp = actuals;
!                 outer = new ClassType(outer, actuals, t) {
                          boolean completed = false;
                          boolean typeArgsSet = false;
                          @Override @DefinedBy(Api.LANGUAGE_MODEL)
                          public Type getEnclosingType() {
                              if (!completed) {
--- 618,11 ---
                   * this additional local variable and depend on field ClassType::typarams_field which `actuals` is
                   * assigned to but then we would have a dependendy on the internal representation of ClassType which
                   * could change in the future
                   */
                  final List<Type> actualsCp = actuals;
!                 outer = new ClassType(outer, actuals, t, List.nil()) {
                          boolean completed = false;
                          boolean typeArgsSet = false;
                          @Override @DefinedBy(Api.LANGUAGE_MODEL)
                          public Type getEnclosingType() {
                              if (!completed) {

*** 691,11 ***
                  //we have seen an enclosing non-generic class
                  if (outer != Type.noType) {
                      t = enterClass(readName(signatureBuffer,
                                                   startSbp,
                                                   sbp - startSbp));
!                     outer = new ClassType(outer, List.nil(), t);
                  }
                  signatureBuffer[sbp++] = (byte)'$';
                  continue;
              case '/':
                  signatureBuffer[sbp++] = (byte)'.';
--- 702,11 ---
                  //we have seen an enclosing non-generic class
                  if (outer != Type.noType) {
                      t = enterClass(readName(signatureBuffer,
                                                   startSbp,
                                                   sbp - startSbp));
!                     outer = new ClassType(outer, List.nil(), t, List.nil());
                  }
                  signatureBuffer[sbp++] = (byte)'$';
                  continue;
              case '/':
                  signatureBuffer[sbp++] = (byte)'.';

*** 1552,10 ***
--- 1563,17 ---
                  sym.flags_field |= PREVIEW_API;
                  setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
              } else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
                  Assert.check(sym.kind == TYP);
                  sym.flags_field |= VALUE_BASED;
+             } else if (proxy.type.tsym.flatName() == syms.migratedValueClassInternalType.tsym.flatName()) {
+                 Assert.check(sym.kind == TYP);
+                 sym.flags_field |= MIGRATED_VALUE_CLASS;
+                 if (needsValueFlag(sym, sym.flags_field)) {
+                     sym.flags_field |= VALUE_CLASS;
+                     sym.flags_field &= ~IDENTITY_TYPE;
+                 }
              } else if (proxy.type.tsym.flatName() == syms.restrictedInternalType.tsym.flatName()) {
                  Assert.check(sym.kind == MTH);
                  sym.flags_field |= RESTRICTED;
              } else {
                  if (proxy.type.tsym == syms.annotationTargetType.tsym) {

*** 1568,10 ***
--- 1586,16 ---
                  }  else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
                      sym.flags_field |= PREVIEW_API;
                      setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
                  }  else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
                      sym.flags_field |= VALUE_BASED;
+                 }  else if (proxy.type.tsym == syms.migratedValueClassType.tsym && sym.kind == TYP) {
+                     sym.flags_field |= MIGRATED_VALUE_CLASS;
+                     if (needsValueFlag(sym, sym.flags_field)) {
+                         sym.flags_field |= VALUE_CLASS;
+                         sym.flags_field &= ~IDENTITY_TYPE;
+                     }
                  }  else if (proxy.type.tsym == syms.restrictedType.tsym) {
                      Assert.check(sym.kind == MTH);
                      sym.flags_field |= RESTRICTED;
                  }
                  proxies.append(proxy);

*** 3062,11 ***
          if (ct.getEnclosingType().hasTag(CLASS))
              enterTypevars(c.owner, ct.getEnclosingType());
  
          // read flags, or skip if this is an inner class
          long f = nextChar();
!         long flags = adjustClassFlags(f);
          if ((flags & MODULE) == 0) {
              if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
              // read own class name and check that it matches
              currentModule = c.packge().modle;
              ClassSymbol self = poolReader.getClass(nextChar());
--- 3086,11 ---
          if (ct.getEnclosingType().hasTag(CLASS))
              enterTypevars(c.owner, ct.getEnclosingType());
  
          // read flags, or skip if this is an inner class
          long f = nextChar();
!         long flags = adjustClassFlags(c, f);
          if ((flags & MODULE) == 0) {
              if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
              // read own class name and check that it matches
              currentModule = c.packge().modle;
              ClassSymbol self = poolReader.getClass(nextChar());

*** 3154,11 ***
              int outerIdx = nextChar();
              int nameIdx = nextChar();
              ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
              Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
              if (name == null) name = names.empty;
!             long flags = adjustClassFlags(nextChar());
              if (outer != null) { // we have a member class
                  if (name == names.empty)
                      name = names.one;
                  ClassSymbol member = enterClass(name, outer);
                  if ((flags & STATIC) == 0) {
--- 3178,11 ---
              int outerIdx = nextChar();
              int nameIdx = nextChar();
              ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
              Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
              if (name == null) name = names.empty;
!             long flags = adjustClassFlags(c, nextChar());
              if (outer != null) { // we have a member class
                  if (name == names.empty)
                      name = names.one;
                  ClassSymbol member = enterClass(name, outer);
                  if ((flags & STATIC) == 0) {

*** 3296,10 ***
--- 3320,15 ---
  /* **********************************************************************
   * Adjusting flags
   ***********************************************************************/
  
      long adjustFieldFlags(long flags) {
+         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
+         if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
+             flags &= ~ACC_STRICT;
+             flags |= STRICT;
+         }
          return flags;
      }
  
      long adjustMethodFlags(long flags) {
          if ((flags & ACC_BRIDGE) != 0) {

*** 3311,16 ***
              flags |= VARARGS;
          }
          return flags;
      }
  
!     long adjustClassFlags(long flags) {
          if ((flags & ACC_MODULE) != 0) {
              flags &= ~ACC_MODULE;
              flags |= MODULE;
          }
!         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
      }
  
      /**
       * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
       * The attribute is only the last component of the original filename, so is unlikely
--- 3340,38 ---
              flags |= VARARGS;
          }
          return flags;
      }
  
!     long adjustClassFlags(ClassSymbol c, long flags) {
          if ((flags & ACC_MODULE) != 0) {
              flags &= ~ACC_MODULE;
              flags |= MODULE;
          }
!         if (((flags & ACC_IDENTITY) != 0 && !isMigratedValueClass(flags)) || (majorVersion < V67.major && (flags & INTERFACE) == 0)) {
+             flags |= IDENTITY_TYPE;
+         } else if (needsValueFlag(c, flags)) {
+             flags |= VALUE_CLASS;
+             flags &= ~IDENTITY_TYPE;
+         }
+         flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
+         return flags;
+     }
+ 
+     private boolean needsValueFlag(Symbol c, long flags) {
+         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
+         if (allowValueClasses) {
+             if (previewClassFile && majorVersion >= V67.major && (flags & INTERFACE) == 0 ||
+                     majorVersion >= V67.major && isMigratedValueClass(flags)) {
+                 return true;
+             }
+         }
+         return false;
+     }
+ 
+     private boolean isMigratedValueClass(long flags) {
+         return allowValueClasses && ((flags & MIGRATED_VALUE_CLASS) != 0);
      }
  
      /**
       * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
       * The attribute is only the last component of the original filename, so is unlikely
< prev index next >