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).

The statements themselves are THE OwnershipStatements (stateless, hold one); this class is the decision, for a value just evaluated in the current scope, of which of them applies.

  • 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
    • isOwnedProducer

      public boolean isOwnedProducer(List<IRInstr> instructions, String target)
      True when the evaluation hands target back at +1, owned by whoever receives it - made OWNED by the instruction that ends it (ValueKind.madeBy(IRInstr), the rule the verifier checks against: a call, constructors and operators included, or a literal) or an escaping chain result: THE question a receiver asks before owning a value rather than borrowing it, or moving it rather than copying it. False for a borrow and for anything not positively identified (the safe, RETAINing side).