Class CodeGenerationAggregates

java.lang.Object
org.ek9lang.compiler.CompilerPhase
org.ek9lang.compiler.phase10.CodeGenerationAggregates
All Implemented Interfaces:
BiFunction<Workspace, CompilerFlags, CompilationPhaseResult>

public class CodeGenerationAggregates extends CompilerPhase
Generate all type of aggregates, typically classes, components, records, etc. See compilationContext.commandLine().targetArchitecture to determine what to prepare to create.

MULTI THREADED over CONSTRUCTS, not over sources - fanning out over sources left one worker holding half the work, because every monomorphised generic is attributed to one module. The phase takes its CompilableProgram reference once, inside compilableProgramAccess.accept, and then works OUTSIDE the lock - see generateOutput. It is sound because this phase is post-freeze: the symbol model and the IR are complete, and nothing here writes to either.

This phase used to be single threaded, and the reason was real rather than cautious: while the loop ran INSIDE accept(), a construct's code generation could trigger lazy symbol resolution (e.g. getAllEffectiveMethods -> type coercion -> ModuleScope.resolveInThisModuleOnly) which re-enters the same lock. A ReentrantLock is reentrant for the HOLDING thread only, so a worker thread attempting that re-entry would deadlock. Not holding the lock removes the possibility entirely: a worker that needs it simply acquires it.

It mattered: at 1M SLOC this phase was 46.3 s of a 91 s compile - 50.9%, on one core - and its share GREW with codebase size (33.9% at 5K), so the compiler used fewer cores the bigger the program (F48).