Skip to content
← Back

src/syntax/process/composite_spill_state.ghul

1
namespace Syntax.Process is
2
use Collections
3
4
use Field = Semantic.Symbols.Field
5
use Node = Trees.Node
6
7
// The state-machine frame field a composite value expression (a
8
// `val ... lav`, or an `if` / `case` / statement list in expression
9
// position) routes its result through when its body suspends.
10
//
11
// Recorded by compile-expressions and read by IL generation, which
12
// treats the presence of an entry as the decision to spill: a
13
// composite with no entry here captures its value inline instead.
14
// The field has to be declared here rather than where it is used,
15
// because the emitter runs after the pass that fixes which rows the
16
// assembly contains, and a field invented later has no row.
17
//
18
// Entries are keyed by (file name, node id), not node object
19
// identity - see Node.node_id. Ids are never reused, so an entry
20
// orphaned by tree replacement can go stale but can never be
21
// served for a different node.
22
class COMPOSITE_SPILL_STORE: NodeStateStore is
23
_field_by_file: MutableMap[string, MutableMap[int, Field]]
24
25
name: string => "composite-spill"
26
27
entry_count: int => _count_entries()
28
29
init(registry: STATE_STORE_REGISTRY) is
30
_field_by_file = MAP[string, MutableMap[int, Field]]()
31
32
registry.register(self)
33
si
34
35
// The frame field recorded for `node`, or null when the
36
// composite is not spilling.
37
get(node: Node) -> Field? is
38
let by_node: MutableMap[int, Field] mut
39
40
if !_field_by_file.try_get_value(node.location.file_name, by_node ref) then
41
return null
42
fi
43
44
let result: Field mut
45
46
if by_node.try_get_value(node.node_id, result ref) then
47
return result
48
fi
49
50
return null
51
si
52
53
set(node: Node, `field: Field) is
54
let file_name = node.location.file_name
55
56
let by_node: MutableMap[int, Field] mut
57
58
if !_field_by_file.try_get_value(file_name, by_node ref) then
59
by_node = MAP[int, Field]()
60
_field_by_file[file_name] = by_node
61
fi
62
63
by_node[node.node_id] = `field
64
si
65
66
// Forgets the field recorded for `node`, if any.
67
remove(node: Node) is
68
let by_node: MutableMap[int, Field] mut
69
70
if _field_by_file.try_get_value(node.location.file_name, by_node ref) then
71
by_node.remove(node.node_id)
72
fi
73
si
74
75
// Forgets every field `owner` declared, across all files: a
76
// state-machine frame that has been dropped and rebuilt leaves
77
// fields nothing will emit.
78
drop_owned_by(owner: Semantic.Symbols.Symbol) is
79
for by_node in _field_by_file.values do
80
let stale = LIST[int]()
81
82
for (node_id, `field) in by_node do
83
if `field.owner == owner then
84
stale.add(node_id)
85
fi
86
od
87
88
for node_id in stale do
89
by_node.remove(node_id)
90
od
91
od
92
si
93
94
drop_file(file_name: string) is
95
_field_by_file.remove(file_name)
96
si
97
98
clear_all() is
99
_field_by_file = MAP[string, MutableMap[int, Field]]()
100
si
101
102
_count_entries() -> int is
103
let result mut = 0
104
105
for by_node in _field_by_file.values do
106
result = result + by_node.count
107
od
108
109
return result
110
si
111
si
112
si