<div dir="ltr">Thanks for the comments, that is a very neat idea!<br><br>I was labouring under a misunderstanding of what the verifier constraints are. My understanding is that at the Java language level, each static final has to be definitely assigned at the end of the static initializer (JLS 8.3.1.2), but the VM has fewer restrictions. Is the only constraint that putstatic is only allowed to write to static final fields inside clinit, and there is no requirement that static finals are definitely assigned in the clinit, so using Unsafe to initialize the fields is fair game?<br><br>I have a rough draft of your approach here: <a href="https://github.com/openjdk/jdk/pull/16191">https://github.com/openjdk/jdk/pull/16191</a><br><br>* It uses reflection and Unsafe.staticFieldOffset for the JVM method.<div><br>* I took a short-cut and disabled generation of values() array. It would be possible to split the values() array across multiple methods, but that would still require additional constant pool entries, and as you described the constant pool size ends up being the limiting factor. I think the values() array could still be a good use of indy or condy.<br><br>With that prototype, I was able to generate an enum with ~32K constants. Each enum name currently uses two constant pool entries (a Utf8 and String entry for the name). Perhaps there's a way to get that down to one entry, and get to ~65k enums.<br><br>I collected some preliminary performance data: with 4000 constants, cold start time is ~400ms with the new codegen and ~700ms without. With ~32K constants, startup takes a full ~17s. From some initial investigation, most of that time is spent in Class.getDeclaredFields and Unsafe.staticFieldOffset.<br></div><div><br></div><div>This has been fun and educational. it also adds complexity to javac, and may not be a clear improvement for non-pathological enums that don't have many thousands of entries.</div><div><br></div><div>Do you think it could be worth pursuing?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Oct 11, 2023 at 6:08 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">P.S. I trust it is clear how the single service method below would be used in the <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)"><clinit></code> of each client enum. One other thing occurred to me: Enums which have bootstrap entanglements with the MethodHandle class would need special treatment. For that reason, it might be better to not pass the argument <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)">MethodHandle enumMemberCreator</code> but rather just call a private static method of a fixed name and signature, within the same enum. That can be easily done with method handles, if those are “on line”, but can also be done with core reflection, which boots up sooner.</p>
<p dir="auto">On 11 Oct 2023, at 18:01, John Rose 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">```
<br>
public static void initializeEnumClass(Lookup enumClassLU, MethodHandle enumMemberCreator) {
<br>
int ordinal = 0;
<br>
if (!enumClassLU.hasPrivateAccess()) throw (IAE);
<br>
Class<? extends Enum> ec = enumClassLU.lookupClass().asSubClass(Enum.class);
<br>
for (Field f : ec.getDeclaredFields()) { //order significant here
<br>
if (f is an enum member) {
<br>
Object e = enumMemberCreator.invokeExact(f, ordinal++);
<br>
// next stuff can be done more directly by Unsafe
<br>
assert(f.get(null) == null); //caller resp.
<br>
f.setAccessible(true);
<br>
f.set(null, e);
<br>
}
<br>
}
<br>
}
<br>
```</p>
<p dir="auto">The creation of the values array should be done in `<clinit>`, as well, or as a condy (yes, that’s a good usage of condy!) and cloned as a fresh copy for each call to `values()`. And it can be done reflectively as well. Just iterate over all the fields and store them into the array. (Use the `ordinal()` as the array index, or just assert that the fields are in the correct order already.)</p>
<p dir="auto">With those two adjustments, to bind enums and build the values array reflectively, your enum would be limited only by the maximum size of the constant pool. That is, you could have up to about 65k enums (but not the whole 2^16).</p>
</blockquote></div>
<div style="white-space:normal">
</div></div></div>
</blockquote></div>