< prev index next >

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

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
--- 1,7 ---
  /*
!  * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

*** 32,20 ***
--- 32,23 ---
  import java.lang.ref.ReferenceQueue;
  import java.lang.ref.WeakReference;
  import java.util.Arrays;
  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 ***
--- 155,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; }

*** 396,10 ***
--- 407,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 (AOTHolder.archivedMethodTypes != null) {
+             MethodType mt = AOTHolder.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},
--- 432,15 ---
              mt = new MethodType(rtype, ptypes);
          }
          mt.form = MethodTypeForm.findForm(mt);
          return internTable.intern(mt);
      }
! 
+     static class AOTHolder {
+         private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
+         private static @Stable HashMap<MethodType,MethodType> archivedMethodTypes;
+     }
  
      /**
       * 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},

*** 432,20 ***
      public static MethodType genericMethodType(int objectArgCount, boolean finalArray) {
          MethodType mt;
          checkSlotCount(objectArgCount);
          int ivarargs = (!finalArray ? 0 : 1);
          int ootIndex = objectArgCount*2 + ivarargs;
!         if (ootIndex < objectOnlyTypes.length) {
!             mt = objectOnlyTypes[ootIndex];
              if (mt != null)  return mt;
          }
          Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
          Arrays.fill(ptypes, Object.class);
          if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
          mt = makeImpl(Object.class, ptypes, true);
!         if (ootIndex < objectOnlyTypes.length) {
!             objectOnlyTypes[ootIndex] = mt;     // cache it here also!
          }
          return mt;
      }
  
      /**
--- 454,20 ---
      public static MethodType genericMethodType(int objectArgCount, boolean finalArray) {
          MethodType mt;
          checkSlotCount(objectArgCount);
          int ivarargs = (!finalArray ? 0 : 1);
          int ootIndex = objectArgCount*2 + ivarargs;
!         if (ootIndex < AOTHolder.objectOnlyTypes.length) {
!             mt = AOTHolder.objectOnlyTypes[ootIndex];
              if (mt != null)  return mt;
          }
          Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
          Arrays.fill(ptypes, Object.class);
          if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
          mt = makeImpl(Object.class, ptypes, true);
!         if (ootIndex < AOTHolder.objectOnlyTypes.length) {
!             AOTHolder.objectOnlyTypes[ootIndex] = mt;     // cache it here also!
          }
          return mt;
      }
  
      /**

*** 1395,6 ***
--- 1417,39 ---
          // 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> copyInternTable() {
+         HashMap<MethodType,MethodType> copy = new HashMap<>();
+ 
+         for (Iterator<MethodType> i = internTable.iterator(); i.hasNext(); ) {
+             MethodType t = i.next();
+             if (canBeArchived(t)) {
+                 copy.put(t, t);
+             }
+         }
+ 
+         return copy;
+     }
+ 
+     static boolean canBeArchived(MethodType t) {
+         if (t.form == null) { // FIXME why?
+             return false;
+         } else {
+             return true;
+         }
+     }
+ 
+     // This is called from C code.
+     static void createArchivedObjects() {
+         for (int i = 0; i < AOTHolder.objectOnlyTypes.length; i++) {
+             MethodType t = AOTHolder.objectOnlyTypes[i];
+             if (t != null && !canBeArchived(t)) {
+                 AOTHolder.objectOnlyTypes[i] = null; // FIXME why?
+             }
+         }
+ 
+         AOTHolder.archivedMethodTypes = copyInternTable();
+     }
  }
< prev index next >