nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
changeset 33333 0bad500ce4e0
parent 33331 273e6a10de22
equal deleted inserted replaced
33332:f180be6368d8 33333:0bad500ce4e0
    87 import java.lang.invoke.MethodHandles.Lookup;
    87 import java.lang.invoke.MethodHandles.Lookup;
    88 import java.util.Objects;
    88 import java.util.Objects;
    89 import jdk.internal.dynalink.CallSiteDescriptor;
    89 import jdk.internal.dynalink.CallSiteDescriptor;
    90 
    90 
    91 /**
    91 /**
    92  * A base class for call site descriptor implementations. Provides reconstruction of the name from the tokens,
    92  * A base class for call site descriptor implementations. Provides
    93  * as well as generally useful {@code equals}, {@code hashCode}, and {@code toString} methods. For security
    93  * reconstruction of the name from the tokens, as well as generally useful
    94  * and performance reasons, subclasses must implement {@link #lookupEquals(AbstractCallSiteDescriptor)},
    94  * {@code equals}, {@code hashCode}, and {@code toString} methods. In order to
       
    95  * both prevent unprivileged access to its internal {@link MethodHandles.Lookup}
       
    96  * object, and at the same time not force privileged access to it from
       
    97  * {@code equals}, {@code hashCode}, and {@code toString} methods, subclasses
       
    98  * must implement {@link #lookupEquals(AbstractCallSiteDescriptor)},
    95  * {@link #lookupHashCode()} and {@link #lookupToString()} methods.
    99  * {@link #lookupHashCode()} and {@link #lookupToString()} methods.
       
   100  * Additionally, {@link #equalsInKind(AbstractCallSiteDescriptor)} should be
       
   101  * overridden instead of {@link #equals(Object)} to compare descriptors in
       
   102  * subclasses; it is only necessary if they have implementation-specific
       
   103  * properties other than the standard name, type, and lookup.
    96  * @param <T> The call site descriptor subclass
   104  * @param <T> The call site descriptor subclass
    97  */
   105  */
    98 public abstract class AbstractCallSiteDescriptor<T extends AbstractCallSiteDescriptor<T>> implements CallSiteDescriptor {
   106 public abstract class AbstractCallSiteDescriptor<T extends AbstractCallSiteDescriptor<T>> implements CallSiteDescriptor {
    99 
   107 
   100     @Override
   108     @Override
   101     public String getName() {
   109     public String getName() {
   102         return appendName(new StringBuilder(getNameLength())).toString();
   110         return appendName(new StringBuilder(getNameLength())).toString();
   103     }
   111     }
   104 
   112 
       
   113     /**
       
   114      * Checks if this call site descriptor is equality to another object. It is
       
   115      * considered equal iff and only if they belong to the exact same class, and
       
   116      * have the same name, method type, and lookup. Subclasses with additional
       
   117      * properties should override
       
   118      * {@link #equalsInKind(AbstractCallSiteDescriptor)} instead of this method.
       
   119      * @param obj the object checked for equality
       
   120      * @return true if they are equal, false otherwise
       
   121      */
   105     @SuppressWarnings("unchecked")
   122     @SuppressWarnings("unchecked")
   106     @Override
   123     @Override
   107     public boolean equals(final Object obj) {
   124     public boolean equals(final Object obj) {
   108         return obj != null && obj.getClass() == getClass() && equalsInKind((T)obj);
   125         return obj != null && obj.getClass() == getClass() && equalsInKind((T)obj);
   109     }
   126     }
   110 
   127 
   111     /**
   128     /**
   112      * Returns true if this call site descriptor is equal to the passed, non-null call site descriptor of the
   129      * Returns true if this call site descriptor is equal to the passed,
   113      * same class.
   130      * non-null call site descriptor of the same class.
   114      * @param csd the other call site descriptor.
   131      * @param csd the other call site descriptor.
   115      * @return true if they are equal.
   132      * @return true if they are equal.
   116      */
   133      */
   117     protected boolean equalsInKind(final T csd) {
   134     protected boolean equalsInKind(final T csd) {
   118         if(csd == this) {
   135         if(csd == this) {
   132         }
   149         }
   133         return lookupEquals(csd);
   150         return lookupEquals(csd);
   134     }
   151     }
   135 
   152 
   136     /**
   153     /**
   137      * Returns true if this call site descriptor's lookup is equal to the other call site descriptor's lookup.
   154      * Returns true if this call site descriptor's lookup is equal to the other
   138      * Typical implementation should try to obtain the other lookup directly without going through
   155      * call site descriptor's lookup. Typical implementation should try to
   139      * {@link #getLookup()} (e.g. directly using the implementation) and then delegate to
   156      * obtain the other lookup directly without going through privileged
       
   157      * {@link #getLookup()} (e.g. by reading the field as the type system
       
   158      * enforces that they are of the same class) and then delegate to
   140      * {@link #lookupsEqual(MethodHandles.Lookup, MethodHandles.Lookup)}.
   159      * {@link #lookupsEqual(MethodHandles.Lookup, MethodHandles.Lookup)}.
   141      * @param other the other lookup
   160      * @param other the other lookup
   142      * @return true if the lookups are equal
   161      * @return true if the lookups are equal
   143      */
   162      */
   144     protected abstract boolean lookupEquals(T other);
   163     protected abstract boolean lookupEquals(T other);
   145 
   164 
       
   165     /**
       
   166      * Compares two lookup objects for value-based equality. They are considered
       
   167      * equal if they have the same
       
   168      * {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and
       
   169      * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()}.
       
   170      * @param l1 first lookup
       
   171      * @param l2 second lookup
       
   172      * @return true if the two lookups are equal, false otherwise.
       
   173      */
   146     protected static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
   174     protected static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
   147         if(l1 == l2) {
   175         if(l1 == l2) {
   148             return true;
   176             return true;
   149         }
   177         } else if (l1 == null || l2 == null) {
   150         if(l1.lookupClass() != l2.lookupClass()) {
   178             return false;
       
   179         } else if(l1.lookupClass() != l2.lookupClass()) {
   151             return false;
   180             return false;
   152         }
   181         }
   153         return l1.lookupModes() == l2.lookupModes();
   182         return l1.lookupModes() == l2.lookupModes();
   154     }
   183     }
   155 
   184 
   162         }
   191         }
   163         return h * 31 + getMethodType().hashCode();
   192         return h * 31 + getMethodType().hashCode();
   164     }
   193     }
   165 
   194 
   166     /**
   195     /**
   167      * Return the hash code of this call site descriptor's {@link Lookup} object. Typical
   196      * Return the hash code of this call site descriptor's {@link Lookup}
   168      * implementation should delegate to {@link #lookupHashCode(MethodHandles.Lookup)}.
   197      * object. Typical implementation should delegate to
   169      * @return the hash code of this call site descriptor's {@link Lookup} object.
   198      * {@link #lookupHashCode(MethodHandles.Lookup)}.
       
   199      * @return the hash code of this call site descriptor's {@link Lookup}
       
   200      * object.
   170      */
   201      */
   171     protected abstract int lookupHashCode();
   202     protected abstract int lookupHashCode();
   172 
   203 
       
   204     /**
       
   205      * Returns a value-based hash code for the passed lookup object. It is
       
   206      * based on the lookup object's
       
   207      * {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and
       
   208      * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()} values.
       
   209      * @param lookup the lookup object.
       
   210      * @return a hash code for the object. Returns 0 for null.
       
   211      */
   173     protected static int lookupHashCode(final Lookup lookup) {
   212     protected static int lookupHashCode(final Lookup lookup) {
   174         return lookup.lookupClass().hashCode() + 31 * lookup.lookupModes();
   213         return lookup != null ? lookup.lookupClass().hashCode() + 31 * lookup.lookupModes() : 0;
   175     }
   214     }
   176 
   215 
   177     @Override
   216     @Override
   178     public String toString() {
   217     public String toString() {
   179         final String mt = getMethodType().toString();
   218         final String mt = getMethodType().toString();
   181         final StringBuilder b = new StringBuilder(l.length() + 1 + mt.length() + getNameLength());
   220         final StringBuilder b = new StringBuilder(l.length() + 1 + mt.length() + getNameLength());
   182         return appendName(b).append(mt).append("@").append(l).toString();
   221         return appendName(b).append(mt).append("@").append(l).toString();
   183     }
   222     }
   184 
   223 
   185     /**
   224     /**
   186      * Return a string representation of this call site descriptor's {@link Lookup} object. Typically will
   225      * Return a string representation of this call site descriptor's
   187      * return {@link Lookup#toString()}.
   226      * {@link Lookup} object. Typically will return
   188      * @return a string representation of this call site descriptor's {@link Lookup} object.
   227      * {@link java.lang.invoke.MethodHandles.Lookup#toString()}.
       
   228      * @return a string representation of this call site descriptor's
       
   229      * {@link Lookup} object.
   189      */
   230      */
   190     protected abstract String lookupToString();
   231     protected abstract String lookupToString();
   191 
   232 
   192     private int getNameLength() {
   233     private int getNameLength() {
   193         final int c = getNameTokenCount();
   234         final int c = getNameTokenCount();