src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java

Print this page




  74        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
  75        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  76        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  77        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  78        BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  79        WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  80        OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  82 */
  83 
  84 package jdk.internal.dynalink.support;
  85 
  86 import java.lang.invoke.MethodHandles;
  87 import java.lang.invoke.MethodHandles.Lookup;
  88 import java.lang.invoke.MethodType;
  89 import java.lang.ref.Reference;
  90 import java.lang.ref.WeakReference;
  91 import java.util.Arrays;
  92 import java.util.Collections;
  93 import java.util.List;

  94 import java.util.StringTokenizer;
  95 import java.util.WeakHashMap;
  96 import jdk.internal.dynalink.CallSiteDescriptor;
  97 
  98 /**
  99  * Usable as a default factory for call site descriptor implementations. It is weakly canonicalizing, meaning it will
 100  * return the same immutable call site descriptor for identical inputs, i.e. repeated requests for a descriptor
 101  * signifying public lookup for "dyn:getProp:color" of type "Object(Object)" will return the same object as long as
 102  * a previously created, at least softly reachable one exists. It also uses several different implementations of the
 103  * {@link CallSiteDescriptor} internally, and chooses the most space-efficient one based on the input.
 104  * @author Attila Szegedi
 105  */
 106 public class CallSiteDescriptorFactory {
 107     private static final WeakHashMap<CallSiteDescriptor, Reference<CallSiteDescriptor>> publicDescs =
 108             new WeakHashMap<>();
 109 
 110 
 111     private CallSiteDescriptorFactory() {
 112     }
 113 
 114     /**
 115      * Creates a new call site descriptor instance. The actual underlying class of the instance is dependent on the
 116      * passed arguments to be space efficient; i.e. if you  only use the public lookup, you'll get back an
 117      * implementation that doesn't waste space on storing the lookup object.
 118      * @param lookup the lookup that determines access rights at the call site. If your language runtime doesn't have
 119      * equivalents of Java access concepts, just use {@link MethodHandles#publicLookup()}. Must not be null.
 120      * @param name the name of the method at the call site. Must not be null.
 121      * @param methodType the type of the method at the call site. Must not be null.
 122      * @return a call site descriptor representing the input. Note that although the method name is "create", it will
 123      * in fact return a weakly-referenced canonical instance.
 124      */
 125     public static CallSiteDescriptor create(final Lookup lookup, final String name, final MethodType methodType) {
 126         name.getClass(); // NPE check
 127         methodType.getClass(); // NPE check
 128         lookup.getClass(); // NPE check
 129         final String[] tokenizedName = tokenizeName(name);
 130         if(isPublicLookup(lookup)) {
 131             return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType));
 132         }
 133         return new LookupCallSiteDescriptor(tokenizedName, methodType, lookup);
 134     }
 135 
 136     static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) {
 137         synchronized(publicDescs) {
 138             final Reference<CallSiteDescriptor> ref = publicDescs.get(desc);
 139             if(ref != null) {
 140                 final CallSiteDescriptor canonical = ref.get();
 141                 if(canonical != null) {
 142                     return canonical;
 143                 }
 144             }
 145             publicDescs.put(desc, createReference(desc));
 146         }
 147         return desc;
 148     }




  74        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
  75        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  76        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  77        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  78        BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  79        WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  80        OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  82 */
  83 
  84 package jdk.internal.dynalink.support;
  85 
  86 import java.lang.invoke.MethodHandles;
  87 import java.lang.invoke.MethodHandles.Lookup;
  88 import java.lang.invoke.MethodType;
  89 import java.lang.ref.Reference;
  90 import java.lang.ref.WeakReference;
  91 import java.util.Arrays;
  92 import java.util.Collections;
  93 import java.util.List;
  94 import java.util.Objects;
  95 import java.util.StringTokenizer;
  96 import java.util.WeakHashMap;
  97 import jdk.internal.dynalink.CallSiteDescriptor;
  98 
  99 /**
 100  * Usable as a default factory for call site descriptor implementations. It is weakly canonicalizing, meaning it will
 101  * return the same immutable call site descriptor for identical inputs, i.e. repeated requests for a descriptor
 102  * signifying public lookup for "dyn:getProp:color" of type "Object(Object)" will return the same object as long as
 103  * a previously created, at least softly reachable one exists. It also uses several different implementations of the
 104  * {@link CallSiteDescriptor} internally, and chooses the most space-efficient one based on the input.
 105  * @author Attila Szegedi
 106  */
 107 public class CallSiteDescriptorFactory {
 108     private static final WeakHashMap<CallSiteDescriptor, Reference<CallSiteDescriptor>> publicDescs =
 109             new WeakHashMap<>();
 110 
 111 
 112     private CallSiteDescriptorFactory() {
 113     }
 114 
 115     /**
 116      * Creates a new call site descriptor instance. The actual underlying class of the instance is dependent on the
 117      * passed arguments to be space efficient; i.e. if you  only use the public lookup, you'll get back an
 118      * implementation that doesn't waste space on storing the lookup object.
 119      * @param lookup the lookup that determines access rights at the call site. If your language runtime doesn't have
 120      * equivalents of Java access concepts, just use {@link MethodHandles#publicLookup()}. Must not be null.
 121      * @param name the name of the method at the call site. Must not be null.
 122      * @param methodType the type of the method at the call site. Must not be null.
 123      * @return a call site descriptor representing the input. Note that although the method name is "create", it will
 124      * in fact return a weakly-referenced canonical instance.
 125      */
 126     public static CallSiteDescriptor create(final Lookup lookup, final String name, final MethodType methodType) {
 127         Objects.requireNonNull(name);
 128         Objects.requireNonNull(methodType);
 129         Objects.requireNonNull(lookup);
 130         final String[] tokenizedName = tokenizeName(name);
 131         if(isPublicLookup(lookup)) {
 132             return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType));
 133         }
 134         return new LookupCallSiteDescriptor(tokenizedName, methodType, lookup);
 135     }
 136 
 137     static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) {
 138         synchronized(publicDescs) {
 139             final Reference<CallSiteDescriptor> ref = publicDescs.get(desc);
 140             if(ref != null) {
 141                 final CallSiteDescriptor canonical = ref.get();
 142                 if(canonical != null) {
 143                     return canonical;
 144                 }
 145             }
 146             publicDescs.put(desc, createReference(desc));
 147         }
 148         return desc;
 149     }