aboutsummaryrefslogtreecommitdiff
path: root/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
blob: 0b12ea1a3a4e784e6f8b9d0c04504ce389ea77db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

# Class construction, destruction and copies

Part of the [subsystem notes](../SUBSYSTEMS.md). Builds on [classes](CLASSES.md); see also
[explicit memory](MEMORY.md) and [exceptions](RUNTIME_CHECKS_EXCEPTIONS.md).

## Construction

- `ConstructorGen.cc` emits recursive field construction in declaration order followed
  by the ordinary NEW method, sharing `emitMethodCall` access checks, argument
  marshalling and exception-aware calls.
- DECLARE zeroes its original storage on every execution; arrays loop over all flat
  elements and default-construct each one.
- Constructor argument lists are class-only. Plain DECLARE, field and array defaults go
  through `emitDefaultConstruct`, which calls NEW only when a parameterless one exists
  (else the object stays zeroed with constructed fields; guide 10.2); DECLARE with
  parentheses uses `emitConstruct`. Explicit NEW method calls do not reconstruct fields.
- `SymbolInfo::IsReference` marks a pointer slot for declared class variables and BYVAL
  class parameters; `symbolAddress` loads their current object address for all value,
  lvalue, address-of, receiver and BYREF paths. Field aliases, this and BYREF
  parameters bind addresses directly.
- Assignment-only `NewExprAST` uses checked memory-library allocation (at least one byte
  for method-only classes), zero initialization and construction, then rebinds
  reference slots or copies into other destinations.
- Ordinary assignment prefers an exact member OPERATOR<-, then permitted BYVAL
  conversions. Without an operator, a marked converting NEW produces a fresh value;
  replacing a non-STRING class this way releases its previous value before transfer.
- Heap objects require explicit keyword DELETE; INHERITS/SUPER remain unsupported.

## Destruction

- `ConstructorGen.cc` also owns `typeNeedsDestruction` and recursive `emitDestroy`:
  ordinary DELETE method first, then fields in reverse declaration order. Explicit
  DELETE method calls remain ordinary calls without field recursion.
- Keyword DELETE resolves a class lvalue, validates its allocation start through
  the memory-library validator before any destruction, destroys it, then releases it
  through the same runtime as FREE;
  aliases remain dangling.
- Stack lifetimes use a per-function `StackObjects` list saved/restored around function
  emission. DECLARE and BYVAL copies share ownership registration, including arrays and
  records with class fields.
- Each record retains its original source line and owning unit so deferred cleanup
  uses the correct __LIB region, even for globals from another unit. It also retains
  the original address, an entry-initialized Alive flag and, for
  arrays, a runtime element count in an entry slot. Array buffer addresses also live in
  entry slots so deferred cleanup never references branch-local bound SSA values.
- Every array registers, even when its elements need no destruction: cleanup runs the
  element-destroy loop only when needed, then `free`s the buffer and nulls the slot, so
  re-DECLARE, RETURN, unwinding and BYVAL copies all release it. BYREF arrays are never
  registered.
- Repeated DECLARE destroys its previous live incarnation first. Alive becomes true only
  after construction or copy completes and is cleared before destruction.
- Rebinding a reference slot with NEW does not change the original address tracked for
  automatic destruction.

## Class copies and temporaries

- Callers construct BYVAL class lvalue arguments with a same-class BYREF OVERLOAD NEW
  when defined, otherwise they copy bits; the callee's RegisterCopy hook takes
  ownership.
- emitOwnedValue constructs lvalue copies and keeps pending arguments Alive until
  marshalling succeeds. RETURN copies lvalues and transfers rvalues.
- Records and BYVAL arrays recursively clone STRING-bearing fields/elements. Other
  owning class fields are copied shallowly (see the
  [copy limits](../PITFALLS/classes.md#copy-limits)).
- StackObject::Temporary uses statement cleanup and deferred temporary-only cleanup
  before local handlers, while ordinary objects remain function-scoped.
- Function-result method receivers are materialized by the same path as operator
  receivers.
- Assignment first selects a member OPERATOR<- with exact parameters preferred; without one, STRING-bearing
  aggregate assignment clones string fields from lvalues or transfers them from rvalues,
  releasing the target's old string fields without invoking the enclosing class
  destructor; other classes are assigned bitwise.