Skip to content

Commit a99ad6c

Browse files
committed
unfinished
1 parent 011e761 commit a99ad6c

File tree

2 files changed

+207
-180
lines changed

2 files changed

+207
-180
lines changed

jane/doc/extensions/stack/intro.md

+35-41
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,59 @@
1-
# Introduction to Local Allocations
1+
# Introduction to Stack Allocations
22

33
See also the full feature [reference](reference.md) and [common pitfalls](pitfalls.md).
44

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:
87

98
```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
1810
...
1911
```
2012

2113
These values live on a separate stack, and are popped off at the end
2214
of the _region_. Generally, the region ends when the surrounding
2315
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.
2518

2619
This helps performance in a couple of ways: first, the same few hot
2720
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,
2922
and so they're safe to use in low-latency code that must currently be
3023
zero-alloc.
3124

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:
3631

3732
```ocaml
38-
# let local_ thing = { foo; bar } in
33+
# let thing = stack_ { foo; bar } in
3934
some_global := thing;;
4035
^^^^^
4136
Error: This value escapes its region
4237
```
4338

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

5347

5448
## Local parameters
5549

5650
Generally, OCaml functions can do whatever they like with their
5751
arguments: use them, return them, capture them in closures or store
5852
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
6054
escape.
6155

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
6357
function parameters:
6458

6559
```ocaml
@@ -106,13 +100,13 @@ val uses_callback : f:(local_ int Foo.Table.t -> 'a) -> 'a
106100

107101
## Inference
108102

109-
The examples above use the `local_` keyword to mark local
103+
The examples above use the `stack_` keyword to mark stack
110104
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.
112106

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
116110
the compiler will allocate this value on the GC heap as usual, while
117111
with the keyword it will instead report an error.
118112

@@ -128,15 +122,15 @@ mark the local parameter in the other module's mli.
128122
## More control
129123

130124
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:
132126

133127
- **Local closures**
134128

135129
```ocaml
136-
let local_ f a b c = ...
130+
let stack_ f a b c = ...
137131
```
138132
139-
defines a function `f` whose closure is itself locally allocated.
133+
defines a function `f` whose closure is itself stack-allocated.
140134
141135
- **Local-returning functions**
142136
@@ -145,7 +139,7 @@ over which values are locally allocated, including:
145139
...
146140
```
147141
148-
defines a function `f` which returns local allocations into its
142+
defines a function `f` which returns local values into its
149143
caller's region.
150144
151145
- **Global fields**
@@ -154,8 +148,8 @@ over which values are locally allocated, including:
154148
type 'a t = { global_ g : 'a }
155149
```
156150
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`.
160154
161155
For more details, read [the reference](./reference.md).

0 commit comments

Comments
 (0)