<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Hi John,<br>
thanks for the comments, some replies below<br>
</p>
<span style="white-space: pre-wrap">
</span>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">That’s true as far as it goes, but it does not specify WHO is making
the guarantee, and the reader may wrongly surmise that it is the VM
which is somehow making the guarantee. In fact it is the code author
(the JDK engineering team!) which makes this guarantee. (That’s why
it is an internal annotation; we can only speak for ourselves.)
I suggest this amended text to avoid misleading the reader:
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">This annotation, a common feature of low-level JDK code, -guarantees- +asserts+ that +the VM may trust+ the field, even though non-final, -can be trusted- not to change after -its initial and only update- +the VM considers its value for optimization+.
</pre>
</blockquote>
</blockquote>
I agree the proposed text is clearer as to who provides the
guarantee and who does the trusting :-)<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
IMO, the JEP and/or API docs could make it clearer that
composite stable values (what I would call composite lazy
values) can be expected to save on footprint, compared
to containers of multiple stable values. A lazy list or
map probably has a compact backing store for its states,
as well as a shared lambda.</pre>
</blockquote>
This is a good point -- there is a reason as to why we didn't go
"fully minimal", and that reason is that we can provide
better-footprint version for some of these types. In that sense, we
have tried to make StableValue a "battery included" API (and, as a
result, some factories you see in there are _not_ primitives, but
the result of playing the API a bit, and seeing which common use
cases popped out more frequently).<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
(Perhaps you considered but dropped an API point to
expose List<StableValue<T>> for some IntFunction<T>.
We can add it later if it pays for itself. </pre>
</blockquote>
We considered it - in almost all cases we have seen, clients really
wanted to interact with a List<T> so we left it -- but it's
something in the back of our mind -- something which few preview
iterations might help to shake out. As you say a new factory can be
added.<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
By the way, your API rightly supports only finite
composites, by ensuring that the relevant domain
(int size for lists, set for functions and maps)
is specified. This allows internal numbering for
the internal stable array that backs the composite.
Later on, we can lift the finiteness restriction
and support open-ended composites. I wrote a POC
of that here:
<a class="moz-txt-link-freetext" href="https://cr.openjdk.org/~jrose/draft/StableList.java.txt">https://cr.openjdk.org/~jrose/draft/StableList.java.txt</a>
</pre>
</blockquote>
That's nice -- I believe Per and Jorn already did some explorations
in this space -- it's doable, but we wanted to draw a line in the
sand (for now). What you suggest makes perfect sense as something to
consider in a later step.<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
The JEP claims you can pass OrderController::new to the
list combinator. It makes a nice demo, but there is a
problem: Either there is an OrderController constructor
that accepts an int argument (to be used as a list index)
or else StableValue::list is fatally flawed, since it
cannot accept a lambda that takes a argument to specify
the index of the lazy value within the list. I see the
draft javadoc has an IntFunction argument to list, so
all is well there; the JEP sample code is oversimplified.
You could add overloads to the API to save the JEP sample
code. (That is, Supplier as well as IntFunction inputs.)</pre>
</blockquote>
Good catch -- this can result in some confusion<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
Personally, I find it odd that the JEP uses the
word “eagerly” several times, but “lazy” (“laziness”)
only once in the context of the class-holder idiom.
I see the list, supplier, function, and map API points
in StableValue as (finite) lazy value combinators.
(Or factories. They are combinators because they
combine with lambdas, although they do not all
produce further functions.)
I also feel a slight dissonance between the
“of” and ofUnset API points and the combinators.
The first pair are used to create stable values
per se, and the second are used to create lazy
values. I don’t have a proposal to improve that.
I don’t think you need to split out LazyList,
LazyMap, and other types for the lazy combinators.</pre>
</blockquote>
Yeah - it's fair to say that this is an area where we don't feel
100% sure yet. Adding new Stable/Lazy types just for the result of
these combinator methods seemed overkill. Another version we
considered was to move these "stable" combinators where they belong
- e.g. as static methods in Supplier, List, Function. But we were a
bit worried about the discoverability aspect (e.g. how would you
know that you can now create a stable int function?)<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
Relatedly, I feel the “of” method is misnamed.
Normally, a method named “of” is the first one
you should reach for when using an API. But in
this case it is the last, the least useful API
point, a stable value with no future changes.
But stable values are all about leaving the
future flexible. Suggest s/of/ofConstant/.
(And personally, I think “ofFoo” methods which
take no arguments are ugly. But that’s just
me, for sure.)</pre>
</blockquote>
We're also not 100% happy about the factory names and we
flip-flopped quite a bit here (Per can testify to that :-) )<br>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
To summarize: There are a number of directions
for future growth of lazy data structures, and
even explicitly imperative ones (using Stable<T>
views of internal states). The existing API
and JEP provide a foundation for this.
There are three possible connections here to
Leyden proper (especially Premain work).
First and most simply, if you have an app that
contains stable values (either scalars or composites),
and the training run binds them, then there is a
reasonable hope that we can include such bindings
in a future version of Leyden. The access paths
which reach the stable values must be made shiftable
first, which means it’s not a slam dunk, but we are
getting there by steps.
(What do I mean by access paths? I mean API points
like static finals and access methods which reach
stable values. A Leyden Premain assembly phase needs
to acquire permission to execute such API points.
This means shifting of class initializers, which
presupposes class initializers that are simple
enough to shift, and transparent enough to be
proved simple enough to shift. Working on it…)</pre>
</blockquote>
<p>Yes. A big question (and something we'd appreciate feedback on)
is how much having the imperative methods are an obstacle to that.
And/or reusing existing API names. For instance, in principle a
stable suppllier can be shifted: it only has a `get` method, so
there's not a lot of API surface to worry about. But, the fact
that a stable supplier has type `Supplier` might, I suppose, make
it hard for bytecode processors.</p>
<p>Our hope is that if you see a Supplier built with
StableValue::supplier, but you happen to know what the lambda will
evaluate to, perhaps you can just replace the stable supplier with
a _constant_ supplier (e.g. Supplier.ofConstant(value)). We don't
have such an API point, but it's not difficult to create such a
supplier.<br>
</p>
<blockquote type="cite" cite="mid:A059169B-B9A4-402A-A401-FC2E745D0177@oracle.com">
<pre class="moz-quote-pre" wrap="">
This can be done, with discipline, in today’s language.
But I have to wonder if, eventually, we will want to
ask the language to help. Full disclosure: That is
why I think we will eventually want lazy statics, which
have those provable properties. But it’s still just
a guess, at this point. If we do add lazy statics,
they will be built on top of something like stable
value composites, I think. Again, that is just a
speculation about the future, but I think the present
work is foundational for many interesting things.</pre>
</blockquote>
<p>Totally agree - exposing "stability" in the language is not
trivial, but we have hopes that stable values could be a useful
tool for compilers to support such a feature.</p>
<p><br>
</p>
<p>Thanks!<br>
Maurizio</p>
<br>
</body>
</html>