condy and enums
Liam Miller-Cushon
cushon at google.com
Mon Oct 9 21:45:51 UTC 2023
Hello,
I'd like to discuss the idea of using constant dynamic in the generated
code for enums.
The possibility of using condy came up in the review thread for
JDK-8241798, which implemented a small change to the code generation
strategy for enums to raise the limit on the number of enum constants. To
recap, there are limits on the number of constants in an enum imposed by
the class file format. The constants are represented as static final
fields, which have to be initialized in the clinit, which eventually runs
into the 64k method size limit:
https://mail.openjdk.org/pipermail/compiler-dev/2020-March/014413.html
https://bugs.openjdk.org/browse/JDK-8241798
I did some recent experimentation into using condy to initialize enum
constants and create the values array. There's a very rough draft here:
https://github.com/openjdk/jdk/pull/16108
With that change the clinit just contains a ldc/putstatus for each
constant, which is 6 bytes per constant, raising the limit on the number of
constants from ~4k today to about 10k.
I am interested in high level feedback about the idea. Does this seem like
a good use of condy, or a bad use of condy? Are there reasons (performance,
maintenance, other things I'm not considering) why using condy in this way
wouldn't be advisable?
One caveat is that it may not be very valuable to raise the limit further.
Four thousand is already a lot of enum constants. I suspect for many
domains where it's necessary to represent >4k values, it will eventually
need to represent >10k values, and that enums are not the best way to model
those domains. So I wouldn't argue for doing this if there end up being a
lot of trade-offs, but if the condy approach was appealing in general
perhaps raising the limit at the same time could be win-win.
Working through the prototype raised some questions about what a production
quality implementation would look like:
Enums with user-defined constructors are currently only handled if the
arguments are static constants. What would the right solution be? Perhaps a
factory method could be synthetized for constants with non-constant
arguments, so condy could still be used to load them.
The class initializer for MethodHandle transitively loads enums, so having
enum class initializers use condy creates a cyclic dependency. The
prototype skips the new strategy for java.base. I could imagine having a
way to opt specific enums out of the new strategy, but having to maintain
multiple code generation strategies for enums does not seem very appealing.
Perhaps there's a way to refactor to break those cycles, or that the lazy
static final field proposal in JDK-8209964 could help here, or something
else.
I'm curious what you think,
Liam
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20231009/2dfd6650/attachment.htm>
More information about the compiler-dev
mailing list