deduplicating lambda methods

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Mar 29 20:02:21 UTC 2018


I wonder if there could be a way to reuse the logic in 
Pool::DynamicMethod - that code is essentially doing the same thing!

Maurizio



On 29/03/18 19:37, B. Blaser wrote:
> On 29 March 2018 at 16:04, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>> In other words, what I'm saying is that the key should be
>> DynamicMethodSymbol, and that we should avoid creating multiple DMS for
>> callsites which have the same properties. That reflects also invariant in
>> javac: symbols are shared (where possible). A similar point holds for class
>> literals, which are modeled as field access to a fictional symbol called
>> 'class' - we should no creating that fictional symbol multiple times, there
>> should be some shared Scope or similar structure somewhere which, given a
>> class C, gives you back the .class symbol associated with C.
>>
>> Maurizio
> I was expecting a simpler key but I think you're right.
> Here is a patch with the full DMS as key.
> All 'javac/lambda' tests are passing successfully, I'll run the others soon...
>
> Bernard
>
>
> diff -r 9925be430918
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
>     Wed Mar 28 14:24:17 2018 +0100
> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
>     Thu Mar 29 20:09:45 2018 +0200
> @@ -226,6 +226,8 @@
>
>           private Map<DedupedLambda, DedupedLambda> dedupedLambdas;
>
> +        private Map<DynMethSymKey, DynamicMethodSymbol> dynMethSyms =
> new HashMap<>();
> +
>           /**
>            * list of deserialization cases
>            */
> @@ -1218,9 +1220,10 @@
>                                               (MethodSymbol)bsm,
>                                               indyType,
>                                               staticArgs.toArray());
> -
>               JCFieldAccess qualifier =
> make.Select(make.QualIdent(site.tsym), bsmName);
> -            qualifier.sym = dynSym;
> +            DynamicMethodSymbol existing = kInfo.dynMethSyms.putIfAbsent(
> +                    new DynMethSymKey(dynSym), dynSym);
> +            qualifier.sym = existing != null ? existing : dynSym;
>               qualifier.type = indyType.getReturnType();
>
>               JCMethodInvocation proxyCall = make.Apply(List.nil(),
> qualifier, indyArgs);
> @@ -1231,6 +1234,63 @@
>           }
>       }
>       //where
> +    private class DynMethSymKey {
> +        private DynamicMethodSymbol sym;
> +
> +        public DynMethSymKey(DynamicMethodSymbol sym) {
> +            this.sym = sym;
> +        }
> +
> +        @Override
> +        public int hashCode() {
> +            return sym.name.hashCode() |
> +                    sym.owner.hashCode() << 8 |
> +                    ((Integer)sym.bsmKind).hashCode() << 16 |
> +                    sym.bsm.hashCode() << 24;
> +        }
> +
> +        @Override
> +        public boolean equals(Object o) {
> +            if ( !(o instanceof DynMethSymKey) )
> +                return false;
> +
> +            DynMethSymKey that = (DynMethSymKey) o;
> +            boolean equals = true;
> +
> +            // name, type, owner
> +            equals &= sym.name == that.sym.name;
> +            equals &= types.isSameType(sym.type, that.sym.type);
> +            equals &= sym.owner == that.sym.owner;
> +
> +            // bsmKind, bsm
> +            equals &= sym.bsmKind == that.sym.bsmKind;
> +            equals &= sym.bsm == that.sym.bsm;
> +
> +            // staticArgs
> +            if (sym.staticArgs.length != that.sym.staticArgs.length)
> +                return false;
> +
> +            for (int i=0; i<sym.staticArgs.length; i++)
> +                equals &= equalsStaticArg(sym.staticArgs[i],
> that.sym.staticArgs[i]);
> +
> +            return equals;
> +        }
> +
> +        private boolean equalsStaticArg(Object arg1, Object arg2) {
> +            Assert.checkNonNull(arg1);
> +            Assert.checkNonNull(arg2);
> +            if (arg1 instanceof Number && arg2 instanceof Number
> +                    || arg1 instanceof String && arg2 instanceof String
> +                    || arg1 instanceof Pool.MethodHandle && arg2
> instanceof Pool.MethodHandle) {
> +                return arg1.equals(arg2);
> +            } else if (arg1 instanceof MethodType && arg2 instanceof
> MethodType) {
> +                return types.isSameType((MethodType)arg1, (MethodType)arg2);
> +            } else {
> +                return false;
> +            }
> +        }
> +    }
> +
>       private List<Type> bsmStaticArgToTypes(List<Object> args) {
>           ListBuffer<Type> argtypes = new ListBuffer<>();
>           for (Object arg : args) {



More information about the amber-dev mailing list