Choosing the best inference leaf is non-deterministic

B. Blaser bsrbnd at gmail.com
Thu Oct 19 17:44:27 UTC 2017


I created the following JBS issue for that:

https://bugs.openjdk.java.net/browse/JDK-8189683

Cheers,
Bernard


On 10 October 2017 at 22:43, B. Blaser <bsrbnd at gmail.com> wrote:
> On 10 October 2017 at 11:45, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>>
>>
>> On 10/10/17 10:26, B. Blaser wrote:
>>>
>>> This is stable enough until we find a failing example;-)
>>>
>>> If you run twice the second example given in [1], you'll see that the
>>> nodes aren't always solved in the same order...
>>>
>>> While there isn't any problem in this case, this non-deterministic
>>> behavior is definitively unsafe, which is probably due to the fact
>>> that the default 'hashCode()' might depend on the reference (memory
>>> location), see [3].
>>>
>>> The 'TreeSet' I suggested yesterday isn't probably a good solution
>>> neither as it uses the comparison method defined to compute the
>>> acyclic graph.
>>>
>>> So, something derived from 'LinkedHashMap' would be better to preserve
>>> the insertion order and to access the elements in O(1). Or, at least,
>>> overriding 'hashCode()' with something more stable while not
>>> preserving the insertion order (a sequential index assigned to each
>>> node when the inference graph is created, for example).
>>>
>>> What do you think?
>>
>> I think we need to understand the source of non-determinism. If that is
>> simply caused by nodes not having stable equals and hashcode, we might as
>> well add those methods, and make the problem go away w/o any extra memory
>> cost. Iteration order could still be non-deterministic in multi-threaded
>> scenario, but that's not a concern with this part of javac.
>>
>> Or, we could look into a more robust data structure - typically
>> LinkedHashSet is used in such cases, which is probably more robust longer
>> term.
>
> I think 'LinkedHashSet' is exactly what we need here, as next.
>
> Thanks!
> Bernard
>
> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
> b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
> @@ -59,6 +59,7 @@
>  import java.util.EnumSet;
>  import java.util.HashMap;
>  import java.util.HashSet;
> +import java.util.LinkedHashSet;
>  import java.util.Map;
>  import java.util.Optional;
>  import java.util.Properties;
> @@ -1705,11 +1706,11 @@
>              class Node extends
> GraphUtils.TarjanNode<ListBuffer<Type>, Node> implements
> DottableNode<ListBuffer<Type>, Node> {
>
>                  /** node dependencies */
> -                Set<Node> deps;
> +                LinkedHashSet<Node> deps;
>
>                  Node(Type ivar) {
>                      super(ListBuffer.of(ivar));
> -                    this.deps = new HashSet<>();
> +                    this.deps = new LinkedHashSet<>();
>                  }
>
>                  @Override
> @@ -1780,7 +1781,7 @@
>                          addDependencies(n.deps);
>                      }
>                      //update deps
> -                    Set<Node> deps2 = new HashSet<>();
> +                    LinkedHashSet<Node> deps2 = new LinkedHashSet<>();
>                      for (Node d : deps) {
>                          if (data.contains(d.data.first())) {
>                              deps2.add(this);
>
>
>> Or we could do both :-)
>>
>> Maurizio
>>
>>>
>>> Bernard
>>>
>>> [3]
>>> https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#hashCode--


More information about the compiler-dev mailing list