nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
changeset 33333 0bad500ce4e0
parent 33007 03119bfefbbf
equal deleted inserted replaced
33332:f180be6368d8 33333:0bad500ce4e0
    85 
    85 
    86 import java.io.Serializable;
    86 import java.io.Serializable;
    87 import java.util.Collections;
    87 import java.util.Collections;
    88 import java.util.LinkedList;
    88 import java.util.LinkedList;
    89 import java.util.List;
    89 import java.util.List;
       
    90 import java.util.Objects;
    90 import jdk.internal.dynalink.linker.GuardedInvocation;
    91 import jdk.internal.dynalink.linker.GuardedInvocation;
    91 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
    92 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
    92 import jdk.internal.dynalink.linker.LinkRequest;
    93 import jdk.internal.dynalink.linker.LinkRequest;
    93 import jdk.internal.dynalink.linker.LinkerServices;
    94 import jdk.internal.dynalink.linker.LinkerServices;
    94 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
    95 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
    95 
    96 
    96 /**
    97 /**
    97  * A composite type-based guarding dynamic linker. When a receiver of a not yet seen class is encountered, all linkers
    98  * A composite type-based guarding dynamic linker. When a receiver of a not yet
    98  * are queried sequentially on their {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} method. The linkers
    99  * seen class is encountered, all linkers are queried sequentially on their
    99  * returning true are then bound to the class, and next time a receiver of same type is encountered, the linking is
   100  * {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} method. The linkers
   100  * delegated to those linkers only, speeding up dispatch.
   101  * returning true are then bound to the class, and next time a receiver of same
       
   102  * type is encountered, the linking is delegated to those linkers only, speeding
       
   103  * up dispatch.
   101  */
   104  */
   102 public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker, Serializable {
   105 public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker, Serializable {
   103     private static final long serialVersionUID = 1L;
   106     private static final long serialVersionUID = 1L;
   104 
   107 
   105     // Using a separate static class instance so there's no strong reference from the class value back to the composite
   108     // Using a separate static class instance so there's no strong reference from the class value back to the composite
   147 
   150 
   148     /**
   151     /**
   149      * Creates a new composite type-based linker.
   152      * Creates a new composite type-based linker.
   150      *
   153      *
   151      * @param linkers the component linkers
   154      * @param linkers the component linkers
       
   155      * @throws NullPointerException if {@code linkers} or any of its elements
       
   156      * are null.
   152      */
   157      */
   153     public CompositeTypeBasedGuardingDynamicLinker(final Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
   158     public CompositeTypeBasedGuardingDynamicLinker(final Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
   154         final List<TypeBasedGuardingDynamicLinker> l = new LinkedList<>();
   159         final List<TypeBasedGuardingDynamicLinker> l = new LinkedList<>();
   155         for(final TypeBasedGuardingDynamicLinker linker: linkers) {
   160         for(final TypeBasedGuardingDynamicLinker linker: linkers) {
   156             l.add(linker);
   161             l.add(Objects.requireNonNull(linker));
   157         }
   162         }
   158         this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()]));
   163         this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()]));
   159     }
   164     }
   160 
   165 
       
   166     /**
       
   167      * Returns true if any of the composite linkers return true from
       
   168      * {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} for the type.
       
   169      * @param type the type to link
       
   170      * @return true if any of the composite linkers can link calls for the
       
   171      * receiver type, false otherwise.
       
   172      */
   161     @Override
   173     @Override
   162     public boolean canLinkType(final Class<?> type) {
   174     public boolean canLinkType(final Class<?> type) {
   163         return !classToLinker.get(type).isEmpty();
   175         return !classToLinker.get(type).isEmpty();
   164     }
   176     }
   165 
   177 
   178         }
   190         }
   179         return null;
   191         return null;
   180     }
   192     }
   181 
   193 
   182     /**
   194     /**
   183      * Optimizes a list of type-based linkers. If a group of adjacent linkers in the list all implement
   195      * Optimizes a list of type-based linkers. If a group of adjacent linkers in
   184      * {@link TypeBasedGuardingDynamicLinker}, they will be replaced with a single instance of
   196      * the list all implement {@link TypeBasedGuardingDynamicLinker}, they will
       
   197      * be replaced with a single instance of
   185      * {@link CompositeTypeBasedGuardingDynamicLinker} that contains them.
   198      * {@link CompositeTypeBasedGuardingDynamicLinker} that contains them.
   186      *
   199      *
   187      * @param linkers the list of linkers to optimize
   200      * @param linkers the list of linkers to optimize
   188      * @return the optimized list
   201      * @return the optimized list
       
   202      * @throws NullPointerException if {@code linkers} or any of its elements
       
   203      * are null.
   189      */
   204      */
   190     public static List<GuardingDynamicLinker> optimize(final Iterable<? extends GuardingDynamicLinker> linkers) {
   205     public static List<GuardingDynamicLinker> optimize(final Iterable<? extends GuardingDynamicLinker> linkers) {
   191         final List<GuardingDynamicLinker> llinkers = new LinkedList<>();
   206         final List<GuardingDynamicLinker> llinkers = new LinkedList<>();
   192         final List<TypeBasedGuardingDynamicLinker> tblinkers = new LinkedList<>();
   207         final List<TypeBasedGuardingDynamicLinker> tblinkers = new LinkedList<>();
   193         for(final GuardingDynamicLinker linker: linkers) {
   208         for(final GuardingDynamicLinker linker: linkers) {
       
   209             Objects.requireNonNull(linker);
   194             if(linker instanceof TypeBasedGuardingDynamicLinker) {
   210             if(linker instanceof TypeBasedGuardingDynamicLinker) {
   195                 tblinkers.add((TypeBasedGuardingDynamicLinker)linker);
   211                 tblinkers.add((TypeBasedGuardingDynamicLinker)linker);
   196             } else {
   212             } else {
   197                 addTypeBased(llinkers, tblinkers);
   213                 addTypeBased(llinkers, tblinkers);
   198                 llinkers.add(linker);
   214                 llinkers.add(linker);