< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodType.java

Print this page
*** 30,22 ***
--- 30,26 ---
  import java.lang.constant.MethodTypeDesc;
  import java.lang.ref.Reference;
  import java.lang.ref.ReferenceQueue;
  import java.lang.ref.WeakReference;
  import java.util.Arrays;
+ import java.util.ArrayList;
  import java.util.Collections;
  import java.util.function.Supplier;
+ import java.util.HashMap;
+ import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.NoSuchElementException;
  import java.util.Objects;
  import java.util.Optional;
  import java.util.StringJoiner;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
  import java.util.stream.Stream;
  
+ import jdk.internal.misc.CDS;
  import jdk.internal.util.ReferencedKeySet;
  import jdk.internal.util.ReferenceKey;
  import jdk.internal.vm.annotation.Stable;
  import sun.invoke.util.BytecodeDescriptor;
  import sun.invoke.util.VerifyType;

*** 152,15 ***
--- 156,23 ---
      private @Stable Object wrapAlt;  // alternative wrapped/unwrapped version and
                                       // private communication for readObject and readResolve
      private @Stable Invokers invokers;   // cache of handy higher-order adapters
      private @Stable String methodDescriptor;  // cache for toMethodDescriptorString
  
+     private final boolean checkArchivable = CDS.isDumpingArchive();
      /**
       * Constructor that performs no copying or validation.
       * Should only be called from the factory method makeImpl
       */
      private MethodType(Class<?> rtype, Class<?>[] ptypes) {
+         if (checkArchivable) {
+             MethodHandleNatives.checkArchivable(rtype);
+             for (var p : ptypes) {
+                 MethodHandleNatives.checkArchivable(p);
+             }
+         }
+ 
          this.rtype = rtype;
          this.ptypes = ptypes;
      }
  
      /*trusted*/ MethodTypeForm form() { return form; }

*** 238,10 ***
--- 250,30 ---
              }
          });
  
      static final Class<?>[] NO_PTYPES = {};
  
+     private static Object[] archivedObjects;
+ 
+     private static @Stable HashMap<MethodType,MethodType> archivedMethodTypes;
+ 
+     private static @Stable MethodType[] objectOnlyTypes;
+ 
+     @SuppressWarnings("unchecked")
+     static void doit() {
+         CDS.initializeFromArchive(MethodType.class);
+         if (archivedObjects != null) {
+             archivedMethodTypes = (HashMap<MethodType,MethodType>)archivedObjects[0];
+             objectOnlyTypes = (MethodType[])archivedObjects[1];
+         } else {
+             objectOnlyTypes = new MethodType[20];
+         }
+     }
+     static {
+         doit();
+     }
+ 
      /**
       * Finds or creates an instance of the given method type.
       * @param rtype  the return type
       * @param ptypes the parameter types
       * @return a method type with the given components

*** 396,10 ***
--- 428,17 ---
      private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
          if (ptypes.length == 0) {
              ptypes = NO_PTYPES; trusted = true;
          }
          MethodType primordialMT = new MethodType(rtype, ptypes);
+         if (archivedMethodTypes != null) {
+             MethodType mt = archivedMethodTypes.get(primordialMT);
+             if (mt != null) {
+                 return mt;
+             }
+         }
+ 
          MethodType mt = internTable.get(primordialMT);
          if (mt != null)
              return mt;
  
          // promote the object to the Real Thing, and reprobe

*** 414,11 ***
              mt = new MethodType(rtype, ptypes);
          }
          mt.form = MethodTypeForm.findForm(mt);
          return internTable.intern(mt);
      }
-     private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
  
      /**
       * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
       * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
       * All parameters and the return type will be {@code Object},
--- 453,10 ---

*** 1389,6 ***
--- 1427,56 ---
          // Return a new validated MethodType for the rtype and ptypes passed from readObject.
          MethodType mt = ((MethodType[])wrapAlt)[0];
          wrapAlt = null;
          return mt;
      }
+ 
+     static HashMap<MethodType,MethodType> archive(Archiver archiver) {
+         HashMap<MethodType,MethodType> archivedSet = new HashMap<>();
+ 
+         for (Iterator<MethodType> i = internTable.iterator(); i.hasNext(); ) {
+             MethodType t = i.next();
+             MethodType a = archiver.clean(t);
+             if (a != null) {
+                 archivedSet.put(a, a);
+             }
+         }
+ 
+         return archivedSet;
+     }
+ 
+     static class Archiver {
+         ArrayList<MethodType> archived = new ArrayList<>();
+ 
+         MethodType clean(MethodType t) {
+             if (t == null || t.form == null) { // HACK!
+                 return null;
+             }
+             if (archived.contains(t)) {
+                 return t;
+             }
+ 
+             archived.add(t);
+             return t;
+         }
+     }
+ 
+     // This is called from C code.
+     static void dumpSharedArchive() {
+         Archiver archiver = new Archiver();
+ 
+         MethodType[] objectOnlyTypesCopy = new MethodType[objectOnlyTypes.length];
+         for (int i = 0; i < objectOnlyTypes.length; i++) {
+             MethodType t = archiver.clean(objectOnlyTypes[i]);
+             if (t != null) {
+                 objectOnlyTypesCopy[i] = t;
+             }
+         }
+ 
+         archivedObjects = new Object[2];
+         archivedObjects[0] = archive(archiver);
+         archivedObjects[1] = objectOnlyTypesCopy;
+ 
+         DirectMethodHandle.dumpSharedArchive();
+         LambdaForm.NamedFunction.dumpSharedArchive();
+     }
  }
< prev index next >