OLD | NEW |
---|---|
(Empty) | |
1 Object allocation and lifetime in ICE | |
JF
2014/12/19 05:34:41
You'll need to link to this document from another
Jim Stichnoth
2014/12/19 15:22:28
Hmm, I guess maybe I need a new document to add a
| |
2 ===================================== | |
3 | |
4 This document discusses object lifetime and scoping issues, starting with | |
5 bitcode parsing and ending with ELF file emission. | |
6 | |
7 Multithreaded translation model | |
8 ------------------------------- | |
9 | |
10 A single thread is responsible for parsing PNaCl bitcode and constructing the | |
JF
2014/12/19 05:34:41
I'd mention that parsing overlaps download.
Jim Stichnoth
2014/12/19 15:22:28
Done.
| |
11 initial high-level ICE. The result is a set of Cfg pointers. The parser thread | |
12 incrementally adds a Cfg pointer to the set after the Cfg is created, and then | |
13 moves on to parse the next function. | |
JF
2014/12/19 05:34:41
I'd call it a queue, since's it's pretty much FIFO
Jim Stichnoth
2014/12/19 15:22:28
Changed all sets to queues. Also added a subsecti
| |
14 | |
15 Multiple translation worker threads draw from the set of Cfg pointers as they | |
16 are added to the set, such that several functions can be translated in parallel. | |
17 The result is a set of assembler buffers, each of which consists of machine code | |
18 plus fixups. | |
19 | |
20 A single thread is responsible for writing the assembler buffers to an ELF file. | |
21 It consumes the assembler buffers from the set that the translation threads | |
22 write to. | |
23 | |
24 This means that Cfgs are created by the parser thread and destroyed by the | |
25 translation thread, and assembler buffers are created by the translation thread | |
JF
2014/12/19 05:34:41
In the middle: new IR nodes are created in a Cfg b
Jim Stichnoth
2014/12/19 15:22:28
Done (including Cfg nodes, instructions, and most
| |
26 and destroyed by the writer thread. | |
27 | |
28 Object lifetimes | |
29 ---------------- | |
30 | |
31 Objects of type Constant, or a subclass of Constant, are pooled globally. The | |
32 pooling is managed by the GlobalContext class. Since Constants are added or | |
33 lookup up by translation threads and the parser thread, access to the constant | |
34 pools, as well as GlobalContext in general, need to be arbitrated by locks. | |
35 (It's possible that if there's too much contention, we can maintain a | |
36 thread-local cache for Constant pool lookups.) Constants live across all | |
37 function translations, and are destroyed only at the end. | |
38 | |
39 Several object types are scoped within the lifetime of the Cfg. These include | |
40 CfgNode, Inst, Variable, and any target-specific subclasses of Inst and Operand. | |
41 When the Cfg is destroyed, these scoped objects are destroyed as well. To keep | |
42 this cheap, the Cfg includes a slab allocator from which these objects are | |
43 allocated, and the objects should not contain fields with non-trivial | |
44 destructors. Most of these fields are POD, but in a couple of cases these | |
45 fields are STL containers. We deal with this, and avoid leaking memory, by | |
46 providing the container with an allocator that uses the Cfg-local slab | |
47 allocator. Since the container allocator generally needs to be stateless, we | |
48 store a pointer to the slab allocator in thread-local storage (TLS). This is | |
49 straightforward since only one Cfg is active at a time. | |
JF
2014/12/19 05:34:41
Only one Cfg is active at a time in a given thread
Jim Stichnoth
2014/12/19 15:22:28
Done.
| |
50 | |
51 Even though there is a one-to-one correspondence between Cfgs and assembler | |
52 buffers, they need to use different allocators. This is because the translation | |
53 thread wants to destroy the Cfg and reclaim all its memory after translation | |
54 completes, but possibly before the assembly buffer is written to the ELF file. | |
JF
2014/12/19 05:34:41
Ownership of the assembly buffers is transfered to
Jim Stichnoth
2014/12/19 15:22:28
Done.
| |
55 | |
56 Allocators and TLS | |
57 ------------------ | |
58 | |
59 Part of the Cfg building, and transformations on the Cfg, include STL container | |
60 operations which may need to allocate additional memory in a stateless fashion. | |
61 This requires maintaining the proper slab allocator pointer in TLS. | |
62 | |
63 When the parser thread creates a new Cfg object, it puts a pointer to the Cfg's | |
64 slab allocator into its own TLS. This is used as the Cfg is built within the | |
65 parser thread. After the Cfg is built, the parser thread clears its allocator | |
66 pointer, adds the new Cfg pointer to the translation set, continues with the | |
67 next function. | |
68 | |
69 When the translation thread grabs a new Cfg pointer, it installs the Cfg's slab | |
70 allocator into its TLS and translates the function. When generating the | |
71 assembly buffer, it must take care not to use the Cfg's slab allocator. If | |
72 there is a slab allocator for the assembler buffer, a pointer to it can also be | |
73 installed in TLS if needed. | |
74 | |
75 The translation thread destroys the Cfg when it is done translating, including | |
76 the Cfg's slab allocator, and clears the allocator pointer from its TLS. | |
77 Likewise, the writer thread destroys the assembler buffer when it is finished | |
78 with it. | |
JF
2014/12/19 05:34:41
Mention tsan testing in a new section.
Jim Stichnoth
2014/12/19 15:22:28
Done.
| |
OLD | NEW |