Chromium Code Reviews| 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 |