Comments on JDK-8198408 please ?
John Rose
john.r.rose at oracle.com
Mon Feb 26 21:46:24 UTC 2018
On Feb 26, 2018, at 9:04 AM, Srikanth <srikanth.adayapalam at oracle.com> wrote:
>
>
> Frederic and I have been discussing the code sequence that javac should produce for certain
> more involved attempts to update value fields using withfield.
>
> Basically for the test case in JDK-8198408, what should be the bytecode generated for
>
> d.c.b.a.x = 11;
>
> where x is an int field and a, b, c and d are value classes. I imagine
> this would call for a.x to be updated via withfield to obtain a', b.a to be updated with a' using withfield to obtain b',
> c.b to be updated with b' using withfield to obtain c' and d.c to be updated with c' using withfield
> to obtain d' and for d' to be finally stored back into d - Is that correct ??
This is taking us away from the close coupling between value-based classes
and value types. I'm pretty sure it's a bad road with no good destinations.
Notice that none of these expressions has a meaning which can be predicted
by referring to value-based object classes:
a.x = 11;
a.p.x = 11;
…
a.p.q.r.s.x = 11;
Not even the first has a meaning predicted from standard Java, since x
is a final field in a value-based class. (The other p/q/r/… fields are final,
but the whole process stops immediately with x.)
Years ago, at the inception of the value types project, we considered a
number of alternative ways to give a meaning to all of these expressions.
They are all overly complex for the limited amount of expressiveness
we think they will purchase.
- disallow (the decision we made)
- turn single level assignment into withfield, disallow others
- allow multiple-level assignment to resolve to subfield descriptors
- generate nested dup;getfield;…;withfield sequences
- make field assignment a distinct API point
The basic problem is that we have to bend the meaning of a.x = 11 with
a value type, to include a change to the value of a. No other Java construct
does this. This is why it's a puzzle to wedge value field assignment into
the language.
Other languages have constructs like this. Nested (flat) C structs behave
like this—and almost nobody uses this language feature. Some languages
have elaborate property-definition mechanisms which can endow such
reference chains with assignable behavior (JS, Perl, VB, looking at you).
But we don't want to go there; at the very least we don't want to get on
a slippery slope that slides us into programmable properties.
> This calls for non-trivial changes to be made to javac - I don't think it is a blocker issue, a solution can be
> found quickly, but it is a radical departure from how code generation in Javac works today.
More fundamentally, even the single level assignment a.x = 11 is a
radical departure. So it's no surprise that javac is unready for such things.
> (at the time of withfield emission for updating a.x with 11, the expression stack has been mostly drained and
> has no trace of the complex sequence of operations that led up to that point. When a' is computed
> by updating a.x with 11 using withfield, we reach a dead end - there is nothing in the expression stack to write
> back to. When the updated field is an instance of field of a value instance that is a local variable, the problem
> is lot simpler - all it calls for an astore which does not expect much from the expression stack as far as the destination
> is concerned, the astore opcode fully specifies the destination)
Even if we support single-level field assignment (as twisted sugar for
withfield) we should *not* support multiple-level field assignment.
In fact, I'm doubting (again, after several years) the wisdom of allowing
even the single-level x.a = 11. It seems to lead the user model into a
swamp. And also contains a paradox, that a subexpression on the LHS
of an assignment gets modified, in addition to the whole LHS.
Dan Smith once very tentatively suggested defining a new compound
assignment operation to capture the subexpression changing behavior,
something vaguely like x += __Edit(a = 11). There are lots of variations on
such syntaxes; they are easy to come up with. And of course the
compound assignment always goes with a plain non-assignment
operator, which would be a very direct representation for withfield,
something like y=__Edit(x, a = 11) or y=__Edit(x.a, 11).
I think we want some sort of "reconstructor" mechanism like _Edit
for scoped-in-place modification of value types. It will take a while
to work out the details of such a thing.
Meanwhile, to provide withfield encodings, the single-level a.x=11
is acceptable, given the understanding that *it will probably go away*
when we figure out a story that allows a more natural notation.
(By natural I mean not natural to existing Java but natural to the
semantic structure of value types. Something like WITH in VB
or Modula-3, or something like Java constructor bodies,
sprinkled into other code as sub-blocks.)
We could also represent withfield directly with a temporary
extra operator: __WithField(a.x, 11). I think I'd prefer that,
because it's more obviously a temporary expedient to be
replaced later. Would that be difficult to prototype in javac?
> Could the experts weigh in on the required sequence please - before we go down too far deep in implementing anyone presumed sequence ?
Thanks for asking. See above; I think this represents significant
parts of Brian's thinking as well as my own.
— John
More information about the valhalla-dev
mailing list