Class VariableMemoryManagement

java.lang.Object
org.ek9lang.compiler.phase7.support.VariableMemoryManagement
All Implemented Interfaces:
BiFunction<Supplier<List<IRInstr>>, VariableDetails, List<IRInstr>>

public final class VariableMemoryManagement extends Object implements BiFunction<Supplier<List<IRInstr>>, VariableDetails, List<IRInstr>>
Calls a supplier of main processing instructions and then adds in the memory management. STACK-BASED: Uses IRGenerationContext to get current scope ID from stack.

ARC ownership-transfer convention (uniform +1): a PRODUCER hands back a value already at +1 (fresh object from a factory/constructor/operator/method — every C-runtime and EK9-generated producer returns owned). The receiver of such a value must therefore only SCOPE_REGISTER it (the eventual scope-exit release consumes that +1) — an additional RETAIN would leak. A BORROW (LOAD/LOAD_FIELD/LOAD_STATIC_FIELD/FUNCTION_INSTANCE of an existing variable/field/singleton the receiver does not own) must RETAIN + SCOPE_REGISTER so it is kept alive for the borrowing scope and released after. We classify by the instruction that produced the target value; anything not clearly a producer defaults to RETAIN + SCOPE_REGISTER (over-retain is a leak — recoverable — whereas under-retain is a use-after-free).

  • Constructor Details

  • Method Details

    • apply

      public List<IRInstr> apply(Supplier<List<IRInstr>> mainProcessing, VariableDetails target)
      Specified by:
      apply in interface BiFunction<Supplier<List<IRInstr>>, VariableDetails, List<IRInstr>>
    • registerIfOwnedProducer

      public List<IRInstr> registerIfOwnedProducer(List<IRInstr> instructions, VariableDetails target)
      SCOPE_REGISTER the target ONLY when it is a freshly produced (+1) value, adding nothing for a borrow.

      This is THE helper for a self-contained operator operand whose result is only borrowed by the following call and must not otherwise be retained — e.g. the question operator's operand: ($$x)? evaluates $$x to a fresh +1 JSON that _isSet only reads, so that +1 must be released at scope exit or it leaks; whereas a plain variable operand x? is a borrow that owns nothing new and needs no management. Unlike apply(Supplier, VariableDetails), a borrow is left completely untouched (no RETAIN), so the common x? IR is unchanged.

      Parameters:
      instructions - the operand-evaluation instructions (mutated in place); its last instruction's result must be target for a producer to be recognised
      target - the operand temp to register when it is a producer
      Returns:
      the same instructions list, with a SCOPE_REGISTER appended iff the operand is a producer