RFR: JDK-8241798: Allow enums to have more constants

Remi Forax forax at univ-mlv.fr
Sun Mar 29 00:12:24 UTC 2020


Hi Liam, 
Having values() initialized is the static block is a common issue once you have a code generator that spit enums. 
I had a similar issue and ends up not using enums but plain old classes in the generator because of that. 

There is another solution, 
you can use constantdynamic and pass the names of the constants (an array) as a bootstrap argument, 
you can go up to 65 635 (the limit in term of number of fields), in fact far less because the constant pool will be full before that point. 

public static MyEnum[] values() { 
ldc "values" [MyEnum [BSM=java/lang/runtime/ConstantEnumMetaFactory] ["constant1", "constant2", ...] 
invokevirtual clone() 
areturn 
} 

The major advantage of using constant dynamic is that if nobody calls the method values(), the array is never initialized. 

And once the VM will suport fields declared as "lazy static final", you can get ride of the static bock because the initialization of the constant fields will be done lazily too. 

Rémi 

> De: "Liam Miller-Cushon" <cushon at google.com>
> À: "compiler-dev" <compiler-dev at openjdk.java.net>
> Envoyé: Dimanche 29 Mars 2020 00:37:24
> Objet: RFR: JDK-8241798: Allow enums to have more constants

> Please consider this change to allow enums to have ~4100 constants (up from the
> current limit of ~2740), by moving the creation of the values array out of the
> clinit to a helper method.

> It's fair to ask whether this is worth doing. Increasing the limit by this
> amount doesn't really change the use-cases enums are suitable for: they still
> can't represent arbitrarily large collections of constants, and if you have an
> enum with >2740 constants you're probably going to want >4100 eventually. On
> the other hand, I don't see any obvious drawbacks to the change (in terms of
> complexity in the compiler, performance impact, or complexity of generated
> code). And other options for increasing the limit would require significantly
> more difficult and longer-term changes (e.g. tackling the method and constant
> pool size limits).

> Another question is whether this is the best code generation strategy. Currently
> javac saves the values array to a field and returns copies of it using clone().
> The approach ecj uses skips the field, and just re-creates the array every time
> values() is called. For now I'm keeping the values field to minimize the
> performance impact of this change, but the ecj approach would avoid that field
> and the helper method.

> bug: [ https://bugs.openjdk.java.net/browse/JDK-8241798 |
> https://bugs.openjdk.java.net/browse/JDK-8241798 ]
> webrev: [ http://cr.openjdk.java.net/~cushon/8241798/webrev.00/ |
> http://cr.openjdk.java.net/~cushon/8241798/webrev.00/ ]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20200329/63ceb6fd/attachment.htm>


More information about the compiler-dev mailing list