on javac flags

B. Blaser bsrbnd at gmail.com
Wed Sep 26 19:26:15 UTC 2018


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