[lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV

Srikanth Adayapalam sadayapalam at openjdk.java.net
Mon Apr 19 06:20:00 UTC 2021

On Fri, 16 Apr 2021 16:37:12 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

>> Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html
> src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java line 546:
>> 544:     }
>> 545: 
>> 546:     void switchPool() {
> Can you explain the rationale behind going down this path, instead of creating a new pool? E.g. could we call ClassWriter.writeClass on two symbols, instead of having a single call generate two things by using this constant pool switching? It feels like I'm missing something here...

Obviously, different approaches possible.
I am documenting my chain of thoughts/observations here:

    - Each invocation of the javac compiler, gets a single ClassWriter instance and a single instance of the byte code generator Gen.
    - The single instance of the code generator Gen instantiates a single instance of the PoolWriter
    - The Pool writer manages all the state associated with the constant pool
    - Given a single invocation of the compiler may call for compiling numerous classes and generating numerous class files, and since each class file has its own constant pool, as each JCClassDecl advances through Gen and gets written out into a class file, the ClassWriter calls PoolWriter.reset() after finished with a writing out a class file. This is so as to allow for the slate to be wiped clean in preparation for the next JCClassDecl being fed to Gen.
It is conceivable that we could have bifurcated the the primitive class source declaration into two completely different ASTs, one rooted at a JCClassDecl for the value projection class and another rooted at a at a JCClassDecl for the reference projection class, each with its own members according the members sorting algorithm outlined in SoV4 and inject them into the pipeline at the suitable stage. Each JCClassDecl advances through the byte code generator Gen and the ClassWriter on its own, gets its own pool and gets written out on its own in this block in com.sun.tools.javac.main.JavaCompiler#genCode

JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
        try {
            if (gen.genClass(env, cdef) && (errorCount() == 0))
                return writer.writeClass(cdef.sym);
        } catch (ClassWriter.PoolOverflow ex) {
            log.error(cdef.pos(), Errors.LimitPool);
        } catch (ClassWriter.StringOverflow ex) {
                      Errors.LimitStringOverflow(ex.value.substring(0, 20)));
        } catch (CompletionFailure ex) {
            chk.completionError(cdef.pos(), ex);
        return null;

Which approach is better may boil down to a matter of taste. I found it extremely simple and straightforward to enhance the PoolWriter to operate on bipartite pools.


PR: https://git.openjdk.java.net/valhalla/pull/386

More information about the valhalla-dev mailing list