<div dir="ltr"><div dir="ltr"><div>The top-line goal for the preload efforts is to trigger the necessary "go and look" behaviour to support calling convention flattening for values. We want the broadest, most reliable mechanism to ensure that we routinely get flattening in the calling convention for value types so that the flattening horizon can extend beyond a single compiled body (ie: a method and its inlines).</div><div><br></div>Summarizing the options presented so far:<div><br></div><div>A) Value classes should be put into the CDS archive to ensure they are loaded early enough, in a group, and in a form that the VM can quickly discover whether calling convention optimizations apply to them. This involves either a class list to create a static archive (allows jdk classes) or using a dynamic archive with AppCDS. Both cases require a "cold run" to generate the data needed for CDS and only capture classes that have been loaded during that run (I think that's correct?).</div><div><br></div><div>B) Use a "Watch List" to list class names that should be looked for. When the name appears, trigger loading early enough to allow calling convention optimizations to apply. Name conflicts are "safe" as the worst case is a class is loaded early in multiple loaders but is only a value in one loader. The watch list can be: global or per-module. It's possible a tool like jlink or jmod could be used to generate the watch list by scanning all the classes included in the jimage/jmod file.</div><div><br></div><div>C) The per-class preload attribute. Each class lists the value classes it may reference to ensure they are loaded early enough. Potentially a lot of duplication as each class in an application would list many of the same value classes.</div><div><br></div><div>Did I miss any?</div><div><br></div><div>There's also another dimension we've touched on: how eager is eager loading. Current preload behaviour is to batch load all the listed classes. Alternatively, loading could wait until one of the classes was observed in method signature / field signature and load on an as-needed basis.</div><div><br></div><div>We've mostly concentrated on preload as an optimization for calling conventions but there may be other uses of the mechanism as well. A user may want to ensure that classes are loaded early to prevent optimizations that need to be walked back later based on their knowledge of application behaviour. For example, ensuring there is always more than a single implementor of an interface loaded to prevent CHA optimizations on some critical path where the second implementation is normally loaded late. Or to ensure an entire sealed hierarchy is loaded together. I haven't put much thought into this yet but expect users will find interesting ways to use "preload" if it's reliable enough for them. (And of course, some will abuse it in ways that hurt their performance as well).</div><div><br></div><div>Which of these options meets the goal ("reliable, routine calling convention optimization for values") best?</div><div><br></div><div>--Dan</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 9, 2023 at 9:38 PM John Rose <<a href="mailto:john.r.rose@oracle.com">john.r.rose@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>
<div><div style="font-family:sans-serif"><div style="white-space:normal">
<p dir="auto">On 9 Jun 2023, at 12:41, Dan Heidinga wrote:</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><p dir="auto">On Thu, Jun 8, 2023 at 4:51 PM John Rose <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>> wrote:</p>
<blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(153,153,153);color:rgb(153,153,153)"><p dir="auto">On 8 Jun 2023, at 9:52, Dan Heidinga wrote:</p>
<p dir="auto">On Thu, Jun 8, 2023 at 12:44 PM John Rose <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>> wrote:</p>
<p dir="auto">On 8 Jun 2023, at 9:01, Dan Heidinga wrote:</p>
<p dir="auto">If we decouple the list of preloadable classes from the classfile, how
<br>
would non-jdk classes be handled?> What if instead of ditching the</p>
<p dir="auto">attribute, or treating it like an</p>
<p dir="auto">optimization, we firmed up the contract and treated it as a guarantee…</p>
<p dir="auto">If we go down this route, let’s consider putting the control information
<br>
into a module file (only) for starters. (Maybe class file later if
<br>
needed.) There would be fewer states to document and test, since (by
<br>
definition) class files could not get out of sync.</p>
<p dir="auto">A module would document, in one mplace, which types it would “prefer” to
<br>
preload in order to optimize its APIs (internal or external).</p>
<p dir="auto">This might lead to more class loading than intended. The current approach
<br>
has each classfile register the list of classes it wants preloaded to get
<br>
the best linkage which means we only have to load those classes if we link
<br>
the original class. There's a natural trigger for the preload and a
<br>
limited set of classes to load.</p>
<p dir="auto">There’s a spectrum of tradeoffs here: We could put preload attributes on
<br>
every method and field, to get the maximum amount of fine-grained lazy
<br>
(pre-)loading, or put them in a global file per JVM instance. The more
<br>
fine-grained, the harder it will be to write compliance testing, I think.</p>
</blockquote><p dir="auto">Agreed. There's a sweet spot between expressiveness and overheads
<br>
(testing, metadata, etc). Classfiles have historically been the place
<br>
where the JVM tracks this kind of information as that fits well with
<br>
separate compilation and avoids the "external metadata" problems of ie:
<br>
GraalVM's extra-linguistic configuration files.</p>
<p dir="auto">When compiling the current class, javac already requires directly
<br>
referenced classes to be findable and thus has the info required to write a
<br>
preload attribute. Does javac necessarily have the same info when
<br>
compiling the module-info classfile? Maybe when finding the non-exported
<br>
packages for the module javac (or jlink? or jmod?) could also find the
<br>
value classes that need preloading?</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">That is what I am assuming. The module file would be edited by those guys. Or (maybe better) a plain flat textual list is put somewhere the JVM can find it.</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><p dir="auto">Moving it into a separate pass like this doesn't feel like quite the right
<br>
fit though as it excludes the classpath and complicates the other tools
<br>
processing of the modules.</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">I think it’s better than that. When we are assembling a program (jlink or a Leyden condenser), the responsibility of publicizing value classes (for Preload) surely belongs to the declaration, not collectively on all the uses.</p>
<p dir="auto">So every module (jmod or whatever) that declares 1 or more value classes (if they are exported, at least) should list them on a publicized watch list.</p>
<p dir="auto">There is no need to replicate these watch lists across all potential API clients of a value class. There are reasons <em>not</em> to do this, since the clients have only partial, provisional information about the values.</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(153,153,153);color:rgb(153,153,153)"><p dir="auto">Moving to a single per-module list loses the natural trigger and may
<br>
pre-load more classes than the application will use. If Module A has
<br>
classes {A, B, C} and each one preloads 5 separate classes, with a
<br>
per-module list that's forcing the loading of 15 additional classes (plus
<br>
supers, etc). With a per-class list, we only preload the classes on a
<br>
per-use basis. More of a pay for what you use model.</p>
<p dir="auto">Is there a natural trigger or way to limit the preloads to what I might
<br>
use
<br>
with the per-module file?</p>
<p dir="auto">That’s a very good question. I think what Preload *really is* is a list
<br>
of “names that may require special handling before using in APIs”. They
<br>
don’t need to be loaded when the preload attribute is parsed; they are
<br>
simply put in a “watch list” to trigger additional loading *when
<br>
necessary*. (This is already true.) So I think if we move the preload
<br>
list to (say) the module level (if not a global file), then the JVM will
<br>
have its watch list. (And, in fewer chunks than if we put all the stuff all
<br>
the time redundantly in all class files that might need them: That requires
<br>
frequent repetition.) The JVM can use its watch list as it does today, with
<br>
watch lists populated separately for each class file.</p>
</blockquote><p dir="auto">I initially thought a global list would lead to issues if two different
<br>
classloaders defined classes of the same name but since this is a "go and
<br>
look" signal, early loading based on name should be fine even in that case
<br>
as each loader that mentions the name would be asked to be asked to load
<br>
their version of the named class. So I think a per-JVM list would be OK
<br>
from that perspective (though I still don't like it).</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">Agreed.</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(153,153,153);color:rgb(153,153,153)"><p dir="auto">To emphasize: A watch list does not require loading. It means, “if you see
<br>
this name at a point where you could use extra class info, then I encourage
<br>
you to load sooner rather than later”. The only reason it is “a thing” at
<br>
all is that the default behavior (of loading either as late as possible, or
<br>
as part of a CDS-like thingy) should be changed only on an explicit signal.</p>
</blockquote><p dir="auto">While true for what the JVM needs, this is hard behaviour to explain to
<br>
users and challenging for compliance test writers (or maybe not if we
<br>
continue to treat preload as an optimization).</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">I’m trying to reduce this to a pure optimization. In that case, “watch lists” are just helpers, which are allowed to fail, and allowed to be garbage.</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><p dir="auto">Is this where we want to
<br>
spend our complexity budget?</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">(No, hence it should be an optimization.)</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><p dir="auto">Part of why I'm circling back to treating
<br>
preload as a per-classfile attribute that forms a requirement on the VM
<br>
rather than as an optimization is that the model becomes clearer for users,
<br>
developers and testers.</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">I think it’s still going to be murky. Why is putting the watch list on the API clients better than putting it on (or near) the value class definitions?</p>
</div><div style="white-space:normal"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(119,119,119);color:rgb(119,119,119)"><blockquote style="margin:0px 0px 5px;padding-left:5px;border-left:2px solid rgb(153,153,153);color:rgb(153,153,153)"><p dir="auto">And, hey, maybe CDS is all the primitive we need here: Just run -Xdump
<br>
with all of your class path loaded. Et voila, no Preload at all.</p>
</blockquote><p dir="auto"> Users may find this behaviour surprising - I ran with a CDS archive and my
<br>
JVM loaded classes earlier than it would have otherwise?</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">CDS has the effect of making class loading in a more timely fashion, and (under Leyden) will almost certainly trigger reordering of loading as well. So promulgating a “watch list” has goals which align with CDS.</p>
<p dir="auto">I’m starting to think that the right “level” to pull for optimizing value-based APIs is to put the value classes in a CDS archive. That is a defacto watch list. The jlink guy should just make a table of all value classes. That’s the best form of Preload I can imagine, frankly.</p>
</div></div></div>
</blockquote></div></div>