1
- # Introduction to Local Allocations
1
+ # Introduction to Stack Allocations
2
2
3
3
See also the full feature [ reference] ( reference.md ) and [ common pitfalls] ( pitfalls.md ) .
4
4
5
- Instead of allocating values normally on the GC heap, local
6
- allocations allow you to stack-allocate values using the new ` local_ `
7
- keyword:
5
+ Instead of allocating values normally on the GC heap, you stack-allocate values
6
+ using the new ` stack_ ` keyword:
8
7
9
8
``` ocaml
10
- let local_ x = { foo; bar } in
11
- ...
12
- ```
13
-
14
- or equivalently, by putting the keyword on the expression itself:
15
-
16
- ``` ocaml
17
- let x = local_ { foo; bar } in
9
+ let x = stack_ { foo; bar } in
18
10
...
19
11
```
20
12
21
13
These values live on a separate stack, and are popped off at the end
22
14
of the _ region_ . Generally, the region ends when the surrounding
23
15
function returns, although read [ the reference] ( reference.md ) for more
24
- details.
16
+ details. Annotating ` stack_ ` on non-allocations is meaningless and trigger type
17
+ errors.
25
18
26
19
This helps performance in a couple of ways: first, the same few hot
27
20
cache lines are constantly reused, so the cache footprint is lower than
28
- usual. More importantly, local allocations will never trigger a GC,
21
+ usual. More importantly, stack allocations will never trigger a GC,
29
22
and so they're safe to use in low-latency code that must currently be
30
23
zero-alloc.
31
24
32
- However, for this to be safe, local allocations must genuinely be
33
- local. Since the memory they occupy is reused quickly, we must ensure
34
- that no dangling references to them escape. This is checked by the
35
- type-checker, and you'll see new error messages if local values leak:
25
+ However, for this to be safe, stack-allocated values must not be used after the
26
+ current region are destroyed. This is ensured by the type-checker as
27
+ follows: stack-allocated values will
28
+ be ` local ` to the current region. Heap-allocated values will be ` global ` . ` local `
29
+ values cannot escape the current region, but ` global ` values can. If a ` local `
30
+ value tries to escape the current region, you'll see error messages:
36
31
37
32
``` ocaml
38
- # let local_ thing = { foo; bar } in
33
+ # let thing = stack_ { foo; bar } in
39
34
some_global := thing;;
40
35
^^^^^
41
36
Error: This value escapes its region
42
37
```
43
38
44
- Most of the types of allocation that OCaml does can be locally
45
- allocated: tuples, records, variants, closures, boxed numbers,
46
- etc. Local allocations are also possible from C stubs, although this
47
- requires code changes to use the new ` caml_alloc_local ` instead of
48
- ` caml_alloc ` . A few types of allocation cannot be locally allocated,
49
- though, including first-class modules, classes and objects, and
50
- exceptions. The contents of mutable fields (inside ` ref ` s, ` array ` s
51
- and mutable record fields) also cannot be locally allocated.
39
+ Most of the types of allocation that OCaml does can be stack-allocated: tuples,
40
+ records, variants, closures, boxed numbers, etc. Stack allocations are also
41
+ possible from C stubs, although this requires code changes to use the new
42
+ ` caml_alloc_local ` instead of ` caml_alloc ` . A few types of allocation cannot be
43
+ stack-allocated, though, including first-class modules, classes and objects,
44
+ and exceptions. The contents of mutable fields (inside ` ref ` s, ` array ` s and
45
+ mutable record fields) also cannot be stack-allocated.
52
46
53
47
54
48
## Local parameters
55
49
56
50
Generally, OCaml functions can do whatever they like with their
57
51
arguments: use them, return them, capture them in closures or store
58
52
them in globals, etc. This is a problem when trying to pass around
59
- locally-allocated values, since we need to guarantee they do not
53
+ ` local ` values, since we need to guarantee they do not
60
54
escape.
61
55
62
- The remedy is that we allow the ` local_ ` keyword to also appear on
56
+ The remedy is that we allow the ` local_ ` keyword to appear on
63
57
function parameters:
64
58
65
59
``` ocaml
@@ -106,13 +100,13 @@ val uses_callback : f:(local_ int Foo.Table.t -> 'a) -> 'a
106
100
107
101
## Inference
108
102
109
- The examples above use the ` local_ ` keyword to mark local
103
+ The examples above use the ` stack_ ` keyword to mark stack
110
104
allocations. In fact, this is not necessary, and the compiler will use
111
- local allocations by default where possible.
105
+ stack allocations by default where possible.
112
106
113
- The only effect of the keyword on e.g. a let binding is to change the
114
- behavior for escaping values: if the bound value looks like it escapes
115
- and therefore cannot be locally allocated, then without the keyword
107
+ The only effect of the keyword on an allocation is to change the
108
+ behavior for escaping values: if the allocation looks like it escapes
109
+ and therefore cannot be stack- allocated, then without the keyword
116
110
the compiler will allocate this value on the GC heap as usual, while
117
111
with the keyword it will instead report an error.
118
112
@@ -128,15 +122,15 @@ mark the local parameter in the other module's mli.
128
122
## More control
129
123
130
124
There are a number of other features that allow more precise control
131
- over which values are locally allocated, including:
125
+ over which values are stack- allocated, including:
132
126
133
127
- ** Local closures**
134
128
135
129
``` ocaml
136
- let local_ f a b c = ...
130
+ let stack_ f a b c = ...
137
131
```
138
132
139
- defines a function `f` whose closure is itself locally allocated.
133
+ defines a function `f` whose closure is itself stack- allocated.
140
134
141
135
- **Local-returning functions**
142
136
@@ -145,7 +139,7 @@ over which values are locally allocated, including:
145
139
...
146
140
```
147
141
148
- defines a function `f` which returns local allocations into its
142
+ defines a function `f` which returns local values into its
149
143
caller's region.
150
144
151
145
- **Global fields**
@@ -154,8 +148,8 @@ over which values are locally allocated, including:
154
148
type 'a t = { global_ g : 'a }
155
149
```
156
150
157
- defines a record type `t` whose `g` field is always known to be on
158
- the GC heap ( and may therefore freely escape regions), even though
159
- the record itself may be locally allocated .
151
+ defines a record type `t` whose `g` field is always known to be `global`
152
+ (and thus on the GC heap and may freely escape regions), even though
153
+ the record itself may be `local` .
160
154
161
155
For more details, read [the reference](./reference.md).
0 commit comments