8025965: Specialized functions with same weight replace each other in TreeSet

Tue, 08 Oct 2013 13:11:15 +0200

author
hannesw
date
Tue, 08 Oct 2013 13:11:15 +0200
changeset 593
025e2ff9e91b
parent 592
8c326f8c6799
child 594
19dba6637f20

8025965: Specialized functions with same weight replace each other in TreeSet
Reviewed-by: jlaskey, sundar

src/jdk/nashorn/internal/runtime/CompiledFunction.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Tue Oct 08 13:02:39 2013 +0200
     1.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Tue Oct 08 13:11:15 2013 +0200
     1.3 @@ -48,6 +48,7 @@
     1.4      }
     1.5  
     1.6      CompiledFunction(final MethodType type, final MethodHandle invoker, final MethodHandle constructor) {
     1.7 +        assert type != null;
     1.8          this.type        = type;
     1.9          this.invoker     = invoker;
    1.10          this.constructor = constructor;
    1.11 @@ -80,7 +81,37 @@
    1.12  
    1.13      @Override
    1.14      public int compareTo(final CompiledFunction o) {
    1.15 -        return weight() - o.weight();
    1.16 +        return compareMethodTypes(type(), o.type());
    1.17 +    }
    1.18 +
    1.19 +    private static int compareMethodTypes(final MethodType ownType, final MethodType otherType) {
    1.20 +        // Comparable interface demands that compareTo() should only return 0 if objects are equal.
    1.21 +        // Failing to meet this requirement causes same weight functions to replace each other in TreeSet,
    1.22 +        // so we go some lengths to come up with an ordering between same weight functions,
    1.23 +        // first falling back to parameter count and then to hash code.
    1.24 +        if (ownType.equals(otherType)) {
    1.25 +            return 0;
    1.26 +        }
    1.27 +
    1.28 +        final int diff = weight(ownType) - weight(otherType);
    1.29 +        if (diff != 0) {
    1.30 +            return diff;
    1.31 +        }
    1.32 +        if (ownType.parameterCount() != otherType.parameterCount()) {
    1.33 +            return ownType.parameterCount() - otherType.parameterCount();
    1.34 +        }
    1.35 +        // We're just interested in not returning 0 here, not correct ordering
    1.36 +        return ownType.hashCode() - otherType.hashCode();
    1.37 +    }
    1.38 +
    1.39 +    @Override
    1.40 +    public boolean equals(Object obj) {
    1.41 +        return obj instanceof CompiledFunction && type().equals(((CompiledFunction)obj).type());
    1.42 +    }
    1.43 +
    1.44 +    @Override
    1.45 +    public int hashCode() {
    1.46 +        return type().hashCode();
    1.47      }
    1.48  
    1.49      private int weight() {
    1.50 @@ -119,14 +150,14 @@
    1.51       * a semantically equivalent linkage can be performed.
    1.52       *
    1.53       * @param mt type to check against
    1.54 -     * @return
    1.55 +     * @return true if types are compatible
    1.56       */
    1.57      boolean typeCompatible(final MethodType mt) {
    1.58 -        final Class<?>[] wantedParams   = mt.parameterArray();
    1.59 -        final Class<?>[] existingParams = type().parameterArray();
    1.60 +        final int wantedParamCount   = mt.parameterCount();
    1.61 +        final int existingParamCount = type.parameterCount();
    1.62  
    1.63          //if we are not examining a varargs type, the number of parameters must be the same
    1.64 -        if (wantedParams.length != existingParams.length && !isVarArgsType(mt)) {
    1.65 +        if (wantedParamCount != existingParamCount && !isVarArgsType(mt)) {
    1.66              return false;
    1.67          }
    1.68  
    1.69 @@ -134,10 +165,10 @@
    1.70          //parameters lengths do not match is if our type ends with a varargs argument.
    1.71          //then every trailing parameter in the given callsite can be folded into it, making
    1.72          //us compatible (albeit slower than a direct specialization)
    1.73 -        final int lastParamIndex = Math.min(wantedParams.length, existingParams.length);
    1.74 +        final int lastParamIndex = Math.min(wantedParamCount, existingParamCount);
    1.75          for (int i = 0; i < lastParamIndex; i++) {
    1.76 -            final Type w = Type.typeFor(wantedParams[i]);
    1.77 -            final Type e = Type.typeFor(existingParams[i]);
    1.78 +            final Type w = Type.typeFor(mt.parameterType(i));
    1.79 +            final Type e = Type.typeFor(type.parameterType(i));
    1.80  
    1.81              //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
    1.82              //we also currently don't support boolean as a javascript function callsite type.

mercurial