Interface ConstructOutputSink
- All Known Implementing Classes:
FileConstructOutputSink, InMemoryConstructOutputSink
The destination used to be welded into every writer as new FileOutputStream(target),
which forced one file per construct - 254,724 of them on a 1M-SLOC compile. That is measurably
the constraint on CODE_GENERATION_AGGREGATES, the largest phase in the compiler: when it
was parallelised, USER time grew 1.10x while SYS time grew 2.55x, and at 34 threads the phase was
back to sequential speed. The computation parallelises; a quarter of a million
creat/write/close sequences contending in the kernel do not.
The files were also an intermediate artefact rather than the deliverable: they used to be
written, then read back off disk to build package.jar, which ek9 -r
runs. Making the destination a policy removed that round trip - the CLI batch path now holds the
bytes and the jar is built from them, an incremental build can write only what changed, and the
LLVM backend can hold everything for a whole-program LTO view.
See SPEC-incremental-builds.md for the full design.
Implementations must be thread-safe. CODE_GENERATION_AGGREGATES fans out over
CONSTRUCTS - one flat list across every source - and a single construct's generation can emit
several classes (the construct itself plus synthesised enum iterators and aspect proxies).
-
Method Summary
-
Method Details
-
write
Accept one generated class.- Parameters:
target- the file this class WOULD occupy. It is the identity of the output, not necessarily a path that gets written: a jar sink relativises it to an entry name, an in-memory sink uses it as a key. Keeping it aFilemeans the naming stays identical to the pre-sink pipeline, which is what makes byte-identical output verifiable.content- the class bytes.
-
read
Read back a class this sink was given, if it has it.This exists because the sink is the single source of generated bytes, and something inside the compile needs to read them back:
ByteCodeDirectiveListenervalidates@BYTECODEdirectives during compilation and used to go straight to the filesystem. That is correct only while the bytes are on the filesystem, so it would fail - loudly, but for a confusing reason - the moment a caller chose a sink that holds them. Asking the sink removes the question rather than documenting it.- Parameters:
target- the same file identity that was passed towrite(File, byte[]).- Returns:
- the bytes, or empty if this sink does not have them.
-