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