on javac flags

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Oct 1 11:49:49 UTC 2018


This comment makes a lot of sense Jon. I believe the first thing to do 
here is to explore some of the use cases of the existing flags, and 
devise an API that would cover them effectively; then come up with a way 
to implement this API, whether it's backed by booleans, enum sets or 
longs, that's something to be decided at a later stage.

Thanks
Maurizio


On 26/09/18 21:15, Jonathan Gibbons wrote:
> Maurizio,
>
> I think it would also be good to separate the storage from the API, to 
> provide
> concise usage within the javac codebase.
>
> For example,
>     sym.hasFlag(Flag.STATIC)
>     sym.setFlag(Flag.PUBLIC)
>     etc
>
> as compared to
>    (sym.flags() & STATIC) != 0
>     sym.flags |= STATIC;
>
> If you get the API right, maybe as a first step, it would then be 
> easier to tweak
> the implementation later on as needed.
>
> -- Jon
>
>
> On 09/26/2018 01:06 PM, Maurizio Cimadamore wrote:
>> Hi Bernard,
>> your solution is clever, but now a symbol has an array of N elements 
>> - which makes it completely unfeasible from a memory footprint 
>> perspective. Although maybe the core of what you are suggesting is - 
>> just use a custom data structure, e.g. something like an immutable 
>> bitset, so that we can share common combinations, etc.
>>
>> Maurizio
>>
>> On 26/09/18 20:26, B. Blaser wrote:
>>> Hi Maurizio,
>>>
>>> On Wed, 26 Sep 2018 at 16:17, Maurizio Cimadamore
>>> <maurizio.cimadamore at oracle.com> wrote:
>>>> Hi,
>>>> In javac we have a Flags class which is used to define a list of 
>>>> all the
>>>> flags that are used, both internally (i.e. javac private flags) and
>>>> externally (i.e ACC_ flags). The assumption is that external flags are
>>>> 16-bit wide, while internal flags are all values above 2^16 (_which 
>>>> can
>>>> fit in a long_).
>>>>
>>>> There are several issues with the current handling of flags:
>>>> [...]
>>>> * checking presence/absence of flags is very tedious; we have many 
>>>> many
>>>> occurrences (600+) of C-like code like:
>>>>
>>>> if ((sym.flags() & STATIC) == 0 && ...
>>>>
>>>> or
>>>>
>>>> (sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) { ... }
>>>>
>>>> [...]
>>>> Where does this leave us? I think with these optimizations the memory
>>>> footprint should be relatively contained - we are essentially 
>>>> trading a
>>>> 64-bit value (long flag) with a 64 bit pointer which might or might 
>>>> not
>>>> point to a fresh new object (if not, no extra cost). Of course this 
>>>> all
>>>> needed to be validated with some real world profiling/JMH 
>>>> benchmark, but
>>>> seems like a direction worth exploring.
>>>>
>>>> Thoughts?
>>> I'm afraid that
>>>
>>> if (!sym.flags().contains(Flag.STATIC) && ...
>>>
>>> would be also tedious, somewhat slow and probably expensive in term of
>>> memory usage...
>>>
>>> I guess I'd be more for something like:
>>>
>>> $ cat OnFlags.java
>>> class OnFlags {
>>>      static enum Flag {
>>>          PUBLIC(0, 0x1), PRIVATE(1, 0x2), INTERNAL(2, 0x0);
>>>
>>>          int index;
>>>          int mask; // maybe 'short' would be enough
>>>
>>>          Flag(int index, int mask) {
>>>              this.index = index;
>>>              this.mask = mask;
>>>          }
>>>      }
>>>
>>>      static class Symbol {
>>>          boolean[] flags = new boolean[Flag.values().length];
>>>      }
>>>
>>>      public static void main(String... args) {
>>>          var sym = new Symbol();
>>>          sym.flags[Flag.PUBLIC.index] = true;
>>>          sym.flags[Flag.INTERNAL.index] = true;
>>>
>>>          int jvmFlags = 0;
>>>          for (Flag f: Flag.values())
>>>              if (sym.flags[f.index])
>>>                  jvmFlags |= f.mask;
>>>
>>>          for (Flag f: Flag.values())
>>>              System.out.println(f + ": " + sym.flags[f.index]);
>>>
>>>          System.out.println("jvm flags " + jvmFlags);
>>>      }
>>> }
>>>
>>> No difference between corresponding internal and external flags, so no
>>> mapping would be necessary.
>>>
>>> Testing a flag would be as fast as simple without much extra memory 
>>> cost:
>>>
>>> if (!sym.flags[Flag.STATIC.index] && ...
>>>
>>> Computing the jvm external flag would be also straightforward:
>>>
>>> int jvmFlags = 0;
>>> for (Flag f: Flag.values())
>>>      if (sym.flags[f.index])
>>>          jvmFlags |= f.mask;
>>>
>>> Opinions?
>>>
>>> Bernard
>>>
>>>> Maurizio
>>
>



More information about the compiler-dev mailing list