On Thu, 12 Jan 2023 21:28:12 GMT, Archie L. Cobbs <d...@openjdk.org> wrote:
>> My point is about who puts ThisRef in the set to begin with. It seems to me >> that ThisRef is put there at the start of a method analysis. After which, >> there's several code points where we say "if there's a direct ThisRef in the >> set, do this, otherwise, if there's an indirect ThisRef in the set, do >> that". But the ThisRef (whether indirect or direct) seems set once and for >> all (when we start the analysis, and then inside visitApply). >> >> There is also this bit in `visitReference`: >> >> >> case SUPER: >> if (this.refs.contains(ThisRef.direct())) >> receiverRefs.add(ThisRef.direct()); >> if (this.refs.contains(ThisRef.indirect())) >> receiverRefs.add(ThisRef.indirect()); >> break; >> >> >> But this doesn't change what I'm saying - there seems to be a general >> property when we execute this analysis which says whether the current >> execution context has a direct `this` or not. This seems to me better >> captured with a boolean, which is then fed back to all the other various >> downstream ref creation. >> >> The main observation, at least for me, is that the code unifies everything >> under refs, when in reality there are different aspects: >> >> * the set of variables that can point to this, whether directly or >> indirectly (this is truly a set) >> * whether the current context has a direct or indirect this (this seems more >> a flag to me) >> * whether the expression on top of stack is direct/indirect this reference >> or not (again, 3 possible values here) - but granted, there `depth` here to >> take into account, so you probably end up with a set (given that we don't >> want to model a scope with its own set) >> >> When reading the code, seeing set expression like containment checks or >> removals for things that doesn't seem to be truly sets (unless I'm missing >> something) was genuinely confusing me. > > I get what you're saying - it seems silly to model what is essentially a > fixed, boolean property with the membership of a singleton in a set field, > rather than with a simple boolean field. > > There is a conceptual trade-off though... a lot of the code relates to > converting `Ref`'s from one type to another. For example, as pointed out > above, a method invocation might convert a `ExprRef` to a `ThisRef`, then to > a `ReturnRef`'s, etc. Having these things all be considered part of the same > family helps conceptually. The fact that a direct `ThisRef` is a singleton is > just a coincidence in this way of looking at things. > > The benefit is the simplicity of being able to think of the data model as > "just a set of references". > > For example, methods like `RefSet.replaceExprs()` become less elegant (or > basically impossible) if there have to be special cases for each type of > reference, whereas currently we can do clean stuff like this: > > > @Override > public void visitReturn(JCReturn tree) { > scan(tree.expr); > refs.replaceExprs(depth, ReturnRef::new); > } > > > But I'm also realizing now that several places can be cleaned up by taking > this event further. E.g., we should replace this code: > > if (refs.contains(ThisRef.direct())) > outerRefs.add(OuterRef.direct()); > if (refs.contains(ThisRef.indirect())) > outerRefs.add(OuterRef.indirect()); > > with something like this: > > refs.mapInto(outerRefs, ThisRef.class, OuterRef::new); > > > I will go through and refactor to do that and clean things up a little more. > >> When reading the code, seeing set expression like containment checks or >> removals for things that doesn't seem to be truly sets (unless I'm missing >> something) was genuinely confusing me. > > Probably my fault for not providing better documentation of the overall "set > of references" conceptual approach. FWIW I added a little bit more in > f83a9cf0. > ```java > ```java > if (refs.contains(ThisRef.direct())) > outerRefs.add(OuterRef.direct()); > if (refs.contains(ThisRef.indirect())) > outerRefs.add(OuterRef.indirect()); > ``` > > > > > > > > > > > > with something like this: > ```java > refs.mapInto(outerRefs, ThisRef.class, OuterRef::new); > ``` > ``` This sounds like a good idea, that idiom is quite widespread, so it should help avoiding repetition. ------------- PR: https://git.openjdk.org/jdk/pull/11874