Skip to content

Commit a3342a7

Browse files
Various fixes on unboxed and kinds (#4024)
* Various fixes on unboxed and kinds * Update jane/doc/extensions/_02-unboxed-types/intro.md Co-authored-by: Richard Eisenberg <[email protected]> * Update jane/doc/extensions/_02-unboxed-types/or-null.md Co-authored-by: Richard Eisenberg <[email protected]> * Update jane/doc/extensions/_05-kinds/intro.md Co-authored-by: Richard Eisenberg <[email protected]> * possible rewrite * new or_null intro * typo --------- Co-authored-by: Richard Eisenberg <[email protected]>
1 parent a6b89b4 commit a3342a7

File tree

3 files changed

+29
-27
lines changed

3 files changed

+29
-27
lines changed

jane/doc/extensions/_02-unboxed-types/intro.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ design decisions and contains additional examples.
118118
## Layouts in module inclusion
119119

120120
Layouts are part of kinds, and therefore work just like kinds for the purposes
121-
of module inclusion. See the [kinds
122-
documentation][../kinds.md#inclusion-and-variance] for more.
121+
of module inclusion. See the [kinds documentation](../../kinds/intro#inclusion-and-variance) for more.
123122

124123
# Unboxed numbers
125124

@@ -140,8 +139,7 @@ the other unboxed types) that has layout
140139
float# ... end`.
141140

142141
Each numeric type has its own library for working with it: `float_u`,
143-
`int32_u`, `int64_u`, and `nativeint_u`. (Outside of Jane Street, these will be
144-
modules in the `janestreet_shims` library.)
142+
`int32_u`, `int64_u`, and `nativeint_u` (all in the `janestreet_shims` library).
145143

146144
* Unboxed constants are written with a prepended `#`.
147145
There is no literal syntax for unboxed vectors: use the `Ocaml_simd_sse` library instead.

jane/doc/extensions/_02-unboxed-types/or-null.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ works.
2121

2222
## The `value_or_null` layout
2323

24-
The key observation powering `or_null` is that ordinary OCaml values are
25-
never equal to the word 0. A pointer will always be non-null (and thus different
26-
from 0), and a tagged integer always has its bottom bit set. Because 0 can
27-
never be a valid pointer, we can safely update the garbage collector not to
24+
The key observation powering `or_null` is that no ordinary OCaml value equals the
25+
word 0. A valid pointer will always be non-null, and an immediate (represented
26+
as a tagged integer) will always have its bottom bit set. Thus, all are
27+
different from 0. Therefore, we can safely update the garbage collector not to
2828
traverse null pointers.
2929

3030
We thus want `t or_null` to be just like `t`, except now with a meaning
@@ -89,7 +89,7 @@ annotation burden on programmers.
8989

9090
## Arrays
9191

92-
The flat-float-array optimization demands that all types in OCaml are *separable*:
92+
The float array optimization demands that all types in OCaml are *separable*:
9393
either all elements of that type are float values, or none of them are. But
9494
`float or_null` is not separable: as possible values, it has all floating-point
9595
numbers, plus the null pointer. Therefore, `float or_null array`s must be forbidden.

jane/doc/extensions/_05-kinds/intro.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ several different dimensions. For example, kinds can be used to identify which
2020
types have values that are passed in floating point registers, or are safely
2121
ignored by the garbage collector.
2222

23-
The kind of a type has four components: the _layout_, the _modal bounds_, the
24-
_with-bounds_, and the _non-modal bounds_. The layout describes the shape of the
23+
The kind of a type has four components:
24+
* the _layout_,
25+
* the _modal bounds_,
26+
* the _with-bounds_,
27+
* and the _non-modal bounds_.
28+
The layout describes the shape of the
2529
data at runtime, and is used to support unboxed types. The modal bounds describe
2630
how different types interact with our mode system. In particular, some types
2731
don't have interesting interactions with some modes, so values of these types
@@ -80,7 +84,7 @@ addition, `int`s are not `float`s and they do not need to be garbage-collected
8084

8185
# The meaning of kinds
8286

83-
In additional to `value`, OxCaml supports layouts like `float64` (unboxed
87+
In addition to `value`, OxCaml supports layouts like `float64` (unboxed
8488
floating point numbers that are passed in SIMD registers), `bits64`
8589
and `bits32` (for types represented by unboxed/untagged integers) and product
8690
layouts like `float64 & bits32` (an unboxed pair that is passed in two
@@ -94,7 +98,7 @@ meaning of the mode and details of the implementation of related features in the
9498
OxCaml runtime. See the documentation for each mode to understand which types
9599
cross on its axis.
96100

97-
Formally, these are called modal _bounds_ because the represent upper or lower
101+
Formally, these are called modal _bounds_ because they represent upper or lower
98102
bounds on the appropriate modal axes. For _future_ modal axes (like portability
99103
and linearity), the kind records an upper bound on the mode of values of this
100104
type. For example, `int` is `mod portable` because if you have an `int` that is
@@ -104,11 +108,11 @@ _expectations_. For example, `int` is `mod contended` because in a place where
104108
an `uncontended` value is expected, it's still safe to use a `contended` int.
105109

106110
Why do past and future modal axes get different treatment in kinds? This is
107-
covered in the "Advanced Topics" section below, but isn't essential to
111+
covered in the [Advanced Topics](#advanced-topics) section below, but isn't essential to
108112
understand for day-to-day use of the system.
109113

110-
The non-modal bounds encode several different properties; see the section
111-
"Non-modal bounds" below. They are called bounds because each non-modal axis
114+
The non-modal bounds encode several different properties; see the
115+
[Non-modal bounds](../non-modal) document. They are called bounds because each non-modal axis
112116
still supports a sub-kinding relationship, where a type of a more specific kind
113117
can be used in place of a variable of a less specific kind.
114118

@@ -130,16 +134,16 @@ contended`, or `value mod portable` and `value mod aliased`.
130134
Adding bounds to a kind always makes the kind more specific, or lower. That is,
131135
for any kind `k`, `k mod <bounds> <= k`.
132136

133-
Along the future modal axes, a lower mode leads to a lower kind. So `value mod
134-
stateless <= value mod observing`, and bounding by the maximum mode has no
135-
effect. However, along the past modal axes, a _higher_ mode leads to a lower
136-
kind. So `value mod contended <= value mod sharing` and bounding by the minimum
137-
mode has no effect. We can think of the past axes as flipped, when used in a
138-
kind. This is because `value mod contended` is more restrictive than `value mod
139-
sharing` (the former contains types that do not care at all about the value of
140-
the contention axis, while the latter contains types that still care about the
141-
distinction between `contended` and `sharing`/`uncontended`), and so we must
142-
flip these past axes (somewhat unfortunately).
137+
Along the future modal axes, a _lower_ mode leads to a lower kind. So `stateless
138+
< observing` leads to `value mod stateless <= value mod observing`, and bounding
139+
by the maximum mode has no effect. However, along the past modal axes, a
140+
_higher_ mode leads to a lower kind. So `shared < contended` leads to `value mod
141+
contended <= value mod shared` and it's bounding by the minimum mode that has no
142+
effect. Thus (beware), past modal axes are flipped, when used in a kind. For
143+
instance, `value mod contended` is _more restrictive_ than `value mod shared`.
144+
The former only contains types that do not care about the value of the
145+
contention axis, while the latter also contains types that care about the
146+
distinction between `contended` and `shared`/`uncontended`.
143147

144148
If you want to get nerdy about it, each individual piece of a kind (the layout
145149
and each possible axis of bounds) is a join semilattice, and the order we're
@@ -210,7 +214,7 @@ by types with any kind (e.g., `Sexpable`).
210214
# With-bounds
211215

212216
Sometimes the kind of a type constructor depends on the kinds of the types that
213-
instantiate its parameters. For example, the type `'a list` can mode cross on
217+
are passed as arguments. For example, the type `'a list` can mode cross on
214218
the portability axis if `'a` does.
215219

216220
We could have a `list` whose kind is restricted to work on types that more cross

0 commit comments

Comments
 (0)