1
1
# Memory Management in Rustc
2
2
3
- Rustc tries to be pretty careful how it manages memory. The compiler allocates
4
- _ a lot_ of data structures throughout compilation, and if we are not careful ,
5
- it will take a lot of time and space to do so.
3
+ Generally rustc tries to be pretty careful how it manages memory.
4
+ The compiler allocates _ a lot_ of data structures throughout compilation,
5
+ and if we are not careful, it will take a lot of time and space to do so.
6
6
7
7
One of the main way the compiler manages this is using [ arena] s and [ interning] .
8
8
@@ -11,16 +11,18 @@ One of the main way the compiler manages this is using [arena]s and [interning].
11
11
12
12
## Arenas and Interning
13
13
14
- We create a LOT of data structures during compilation. For performance reasons,
15
- we allocate them from a global memory pool; they are each allocated once from a
16
- long-lived * arena* . This is called _ arena allocation_ . This system reduces
17
- allocations/deallocations of memory. It also allows for easy comparison of
18
- types for equality: for each interned type ` X ` , we implemented [ `PartialEq for
19
- X` ][peqimpl], so we can just compare pointers. The [ ` CtxtInterners`] type
20
- contains a bunch of maps of interned types and the arena itself.
14
+ Since A LOT of data structures are created during compilation, for performance
15
+ reasons, we allocate them from a global memory pool.
16
+ Each are allocated once from a long-lived * arena* .
17
+ This is called _ arena allocation_ .
18
+ This system reduces allocations/deallocations of memory.
19
+ It also allows for easy comparison of types (more on types [ here] ( ./ty.md ) ) for equality:
20
+ for each interned type ` X ` , we implemented [ ` PartialEq ` for X] [ peqimpl ] ,
21
+ so we can just compare pointers.
22
+ The [ ` CtxtInterners ` ] type contains a bunch of maps of interned types and the arena itself.
21
23
22
- [ peqimpl ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#implementations
23
24
[ `CtxtInterners` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CtxtInterners.html#structfield.arena
25
+ [ peqimpl ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#implementations
24
26
25
27
### Example: ` ty::TyKind `
26
28
@@ -30,7 +32,7 @@ compiler doesn’t naively allocate from the buffer. Instead, we check if that
30
32
type was already constructed. If it was, we just get the same pointer we had
31
33
before, otherwise we make a fresh pointer. With this schema if we want to know
32
34
if two types are the same, all we need to do is compare the pointers which is
33
- efficient. ` TyKind ` should never be constructed on the stack, and it would be unusable
35
+ efficient. [ ` TyKind ` ] should never be constructed on the stack, and it would be unusable
34
36
if done so.
35
37
You always allocate them from this arena and you always intern them so they are
36
38
unique.
@@ -43,26 +45,33 @@ to that buffer is freed and our `'tcx` references would be invalid.
43
45
In addition to types, there are a number of other arena-allocated data structures that you can
44
46
allocate, and which are found in this module. Here are a few examples:
45
47
46
- - [ ` GenericArgs ` ] , allocated with ` mk_args ` – this will intern a slice of types, often used
48
+ - [ ` GenericArgs ` ] , allocated with [ ` mk_args ` ] – this will intern a slice of types, often used
47
49
to specify the values to be substituted for generics args (e.g. ` HashMap<i32, u32> ` would be
48
50
represented as a slice ` &'tcx [tcx.types.i32, tcx.types.u32] ` ).
49
51
- [ ` TraitRef ` ] , typically passed by value – a ** trait reference** consists of a reference to a trait
50
52
along with its various type parameters (including ` Self ` ), like ` i32: Display ` (here, the def-id
51
53
would reference the ` Display ` trait, and the args would contain ` i32 ` ). Note that ` def-id ` is
52
54
defined and discussed in depth in the [ ` AdtDef and DefId ` ] [ adtdefid ] section.
53
- - [ ` Predicate ` ] defines something the trait system has to prove (see ` traits ` module).
55
+ - [ ` Predicate ` ] defines something the trait system has to prove (see [ traits] module).
54
56
55
57
[ `GenericArgs` ] : ./ty_module/generic_arguments.md#the-genericargs-type
56
58
[ adtdefid ] : ./ty_module/generic_arguments.md#adtdef-and-defid
57
59
[ `TraitRef` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html
60
+ [ `AdtDef` and `DefId` ] : ./ty.md#adts-representation
61
+ [ `def-id` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
62
+ [ `GenericArgs` ] : ./generic_arguments.html#GenericArgs
63
+ [ `mk_args` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args
64
+ [ adtdefid ] : ./ty_module/generic_arguments.md#adtdef-and-defid
58
65
[ `Predicate` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
59
-
66
+ [ `TraitRef` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
60
67
[ `ty::TyKind` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html
68
+ [ `TyKind` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/ty_kind/enum.TyKind.html
69
+ [ traits ] : ./traits/resolution.md
61
70
62
- ## The tcx and how it uses lifetimes
71
+ ## The ` tcx ` and how it uses lifetimes
63
72
64
- The ` tcx ` (" typing context" ) is the central data structure in the compiler. It is the context that
65
- you use to perform all manner of queries. The struct ` TyCtxt ` defines a reference to this shared
73
+ The typing context ( ` tcx ` ) is the central data structure in the compiler. It is the context that
74
+ you use to perform all manner of queries. The ` struct ` [ ` TyCtxt ` ] defines a reference to this shared
66
75
context:
67
76
68
77
``` rust,ignore
@@ -76,10 +85,13 @@ As you can see, the `TyCtxt` type takes a lifetime parameter. When you see a ref
76
85
lifetime like ` 'tcx ` , you know that it refers to arena-allocated data (or data that lives as long as
77
86
the arenas, anyhow).
78
87
88
+ [ `TyCtxt` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
89
+
79
90
### A Note On Lifetimes
80
91
81
92
The Rust compiler is a fairly large program containing lots of big data
82
- structures (e.g. the AST, HIR, and the type system) and as such, arenas and
93
+ structures (e.g. the [ Abstract Syntax Tree (AST)] [ ast ] , [ High-Level Intermediate
94
+ Representation (` HIR ` )] [ hir ] , and the type system) and as such, arenas and
83
95
references are heavily relied upon to minimize unnecessary memory use. This
84
96
manifests itself in the way people can plug into the compiler (i.e. the
85
97
[ driver] ( ./rustc-driver.md ) ), preferring a "push"-style API (callbacks) instead
@@ -90,4 +102,6 @@ duplication while also preventing a lot of the ergonomic issues due to many
90
102
pervasive lifetimes. The [ ` rustc_middle::ty::tls ` ] [ tls ] module is used to access these
91
103
thread-locals, although you should rarely need to touch it.
92
104
105
+ [ ast ] : ./ast-validation.md
106
+ [ hir ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/index.html
93
107
[ tls ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/tls/index.html
0 commit comments