on javac flags
Jonathan Gibbons
jonathan.gibbons at oracle.com
Wed Sep 26 20:15:10 UTC 2018
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