xref: /aosp_15_r20/external/swiftshader/third_party/subzero/docs/ALLOCATION.rst (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard WorkerObject allocation and lifetime in ICE
2*03ce13f7SAndroid Build Coastguard Worker=====================================
3*03ce13f7SAndroid Build Coastguard Worker
4*03ce13f7SAndroid Build Coastguard WorkerThis document discusses object lifetime and scoping issues, starting with
5*03ce13f7SAndroid Build Coastguard Workerbitcode parsing and ending with ELF file emission.
6*03ce13f7SAndroid Build Coastguard Worker
7*03ce13f7SAndroid Build Coastguard WorkerMultithreaded translation model
8*03ce13f7SAndroid Build Coastguard Worker-------------------------------
9*03ce13f7SAndroid Build Coastguard Worker
10*03ce13f7SAndroid Build Coastguard WorkerA single thread is responsible for parsing PNaCl bitcode (possibly concurrently
11*03ce13f7SAndroid Build Coastguard Workerwith downloading the bitcode file) and constructing the initial high-level ICE.
12*03ce13f7SAndroid Build Coastguard WorkerThe result is a queue of Cfg pointers.  The parser thread incrementally adds a
13*03ce13f7SAndroid Build Coastguard WorkerCfg pointer to the queue after the Cfg is created, and then moves on to parse
14*03ce13f7SAndroid Build Coastguard Workerthe next function.
15*03ce13f7SAndroid Build Coastguard Worker
16*03ce13f7SAndroid Build Coastguard WorkerMultiple translation worker threads draw from the queue of Cfg pointers as they
17*03ce13f7SAndroid Build Coastguard Workerare added to the queue, such that several functions can be translated in parallel.
18*03ce13f7SAndroid Build Coastguard WorkerThe result is a queue of assembler buffers, each of which consists of machine code
19*03ce13f7SAndroid Build Coastguard Workerplus fixups.
20*03ce13f7SAndroid Build Coastguard Worker
21*03ce13f7SAndroid Build Coastguard WorkerA single thread is responsible for writing the assembler buffers to an ELF file.
22*03ce13f7SAndroid Build Coastguard WorkerIt consumes the assembler buffers from the queue that the translation threads
23*03ce13f7SAndroid Build Coastguard Workerwrite to.
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard WorkerThis means that Cfgs are created by the parser thread and destroyed by the
26*03ce13f7SAndroid Build Coastguard Workertranslation thread (including Cfg nodes, instructions, and most kinds of
27*03ce13f7SAndroid Build Coastguard Workeroperands), and assembler buffers are created by the translation thread and
28*03ce13f7SAndroid Build Coastguard Workerdestroyed by the writer thread.
29*03ce13f7SAndroid Build Coastguard Worker
30*03ce13f7SAndroid Build Coastguard WorkerDeterministic execution
31*03ce13f7SAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^
32*03ce13f7SAndroid Build Coastguard Worker
33*03ce13f7SAndroid Build Coastguard WorkerAlthough code randomization is a key aspect of security, deterministic and
34*03ce13f7SAndroid Build Coastguard Workerrepeatable translation is sometimes needed, e.g. for regression testing.
35*03ce13f7SAndroid Build Coastguard WorkerMultithreaded translation introduces potential for randomness that may need to
36*03ce13f7SAndroid Build Coastguard Workerbe made deterministic.
37*03ce13f7SAndroid Build Coastguard Worker
38*03ce13f7SAndroid Build Coastguard Worker* Bitcode parsing is sequential, so it's easy to use a FIFO queue to keep the
39*03ce13f7SAndroid Build Coastguard Worker  translation queue in deterministic order.  But since translation is
40*03ce13f7SAndroid Build Coastguard Worker  multithreaded, FIFO order for the assembler buffer queue may not be
41*03ce13f7SAndroid Build Coastguard Worker  deterministic.  The writer thread would be responsible for reordering the
42*03ce13f7SAndroid Build Coastguard Worker  buffers, potentially waiting for slower translations to complete even if other
43*03ce13f7SAndroid Build Coastguard Worker  assembler buffers are available.
44*03ce13f7SAndroid Build Coastguard Worker
45*03ce13f7SAndroid Build Coastguard Worker* Different translation threads may add new constant pool entries at different
46*03ce13f7SAndroid Build Coastguard Worker  times.  Some constant pool entries are emitted as read-only data.  This
47*03ce13f7SAndroid Build Coastguard Worker  includes floating-point constants for x86, as well as integer immediate
48*03ce13f7SAndroid Build Coastguard Worker  randomization through constant pooling.  These constant pool entries are
49*03ce13f7SAndroid Build Coastguard Worker  emitted after all assembler buffers have been written.  The writer needs to be
50*03ce13f7SAndroid Build Coastguard Worker  able to sort them deterministically before emitting them.
51*03ce13f7SAndroid Build Coastguard Worker
52*03ce13f7SAndroid Build Coastguard WorkerObject lifetimes
53*03ce13f7SAndroid Build Coastguard Worker----------------
54*03ce13f7SAndroid Build Coastguard Worker
55*03ce13f7SAndroid Build Coastguard WorkerObjects of type Constant, or a subclass of Constant, are pooled globally.  The
56*03ce13f7SAndroid Build Coastguard Workerpooling is managed by the GlobalContext class.  Since Constants are added or
57*03ce13f7SAndroid Build Coastguard Workerlooked up by translation threads and the parser thread, access to the constant
58*03ce13f7SAndroid Build Coastguard Workerpools, as well as GlobalContext in general, need to be arbitrated by locks.
59*03ce13f7SAndroid Build Coastguard Worker(It's possible that if there's too much contention, we can maintain a
60*03ce13f7SAndroid Build Coastguard Workerthread-local cache for Constant pool lookups.)  Constants live across all
61*03ce13f7SAndroid Build Coastguard Workerfunction translations, and are destroyed only at the end.
62*03ce13f7SAndroid Build Coastguard Worker
63*03ce13f7SAndroid Build Coastguard WorkerSeveral object types are scoped within the lifetime of the Cfg.  These include
64*03ce13f7SAndroid Build Coastguard WorkerCfgNode, Inst, Variable, and any target-specific subclasses of Inst and Operand.
65*03ce13f7SAndroid Build Coastguard WorkerWhen the Cfg is destroyed, these scoped objects are destroyed as well.  To keep
66*03ce13f7SAndroid Build Coastguard Workerthis cheap, the Cfg includes a slab allocator from which these objects are
67*03ce13f7SAndroid Build Coastguard Workerallocated, and the objects should not contain fields with non-trivial
68*03ce13f7SAndroid Build Coastguard Workerdestructors.  Most of these fields are POD, but in a couple of cases these
69*03ce13f7SAndroid Build Coastguard Workerfields are STL containers.  We deal with this, and avoid leaking memory, by
70*03ce13f7SAndroid Build Coastguard Workerproviding the container with an allocator that uses the Cfg-local slab
71*03ce13f7SAndroid Build Coastguard Workerallocator.  Since the container allocator generally needs to be stateless, we
72*03ce13f7SAndroid Build Coastguard Workerstore a pointer to the slab allocator in thread-local storage (TLS).  This is
73*03ce13f7SAndroid Build Coastguard Workerstraightforward since on any of the threads, only one Cfg is active at a time,
74*03ce13f7SAndroid Build Coastguard Workerand a given Cfg is only active in one thread at a time (either the parser
75*03ce13f7SAndroid Build Coastguard Workerthread, or at most one translation thread, or the writer thread).
76*03ce13f7SAndroid Build Coastguard Worker
77*03ce13f7SAndroid Build Coastguard WorkerEven though there is a one-to-one correspondence between Cfgs and assembler
78*03ce13f7SAndroid Build Coastguard Workerbuffers, they need to use different allocators.  This is because the translation
79*03ce13f7SAndroid Build Coastguard Workerthread wants to destroy the Cfg and reclaim all its memory after translation
80*03ce13f7SAndroid Build Coastguard Workercompletes, but possibly before the assembly buffer is written to the ELF file.
81*03ce13f7SAndroid Build Coastguard WorkerOwnership of the assembler buffer and its allocator are transferred to the
82*03ce13f7SAndroid Build Coastguard Workerwriter thread after translation completes, similar to the way ownership of the
83*03ce13f7SAndroid Build Coastguard WorkerCfg and its allocator are transferred to the translation thread after parsing
84*03ce13f7SAndroid Build Coastguard Workercompletes.
85*03ce13f7SAndroid Build Coastguard Worker
86*03ce13f7SAndroid Build Coastguard WorkerAllocators and TLS
87*03ce13f7SAndroid Build Coastguard Worker------------------
88*03ce13f7SAndroid Build Coastguard Worker
89*03ce13f7SAndroid Build Coastguard WorkerPart of the Cfg building, and transformations on the Cfg, include STL container
90*03ce13f7SAndroid Build Coastguard Workeroperations which may need to allocate additional memory in a stateless fashion.
91*03ce13f7SAndroid Build Coastguard WorkerThis requires maintaining the proper slab allocator pointer in TLS.
92*03ce13f7SAndroid Build Coastguard Worker
93*03ce13f7SAndroid Build Coastguard WorkerWhen the parser thread creates a new Cfg object, it puts a pointer to the Cfg's
94*03ce13f7SAndroid Build Coastguard Workerslab allocator into its own TLS.  This is used as the Cfg is built within the
95*03ce13f7SAndroid Build Coastguard Workerparser thread.  After the Cfg is built, the parser thread clears its allocator
96*03ce13f7SAndroid Build Coastguard Workerpointer, adds the new Cfg pointer to the translation queue, continues with the
97*03ce13f7SAndroid Build Coastguard Workernext function.
98*03ce13f7SAndroid Build Coastguard Worker
99*03ce13f7SAndroid Build Coastguard WorkerWhen the translation thread grabs a new Cfg pointer, it installs the Cfg's slab
100*03ce13f7SAndroid Build Coastguard Workerallocator into its TLS and translates the function.  When generating the
101*03ce13f7SAndroid Build Coastguard Workerassembly buffer, it must take care not to use the Cfg's slab allocator.  If
102*03ce13f7SAndroid Build Coastguard Workerthere is a slab allocator for the assembler buffer, a pointer to it can also be
103*03ce13f7SAndroid Build Coastguard Workerinstalled in TLS if needed.
104*03ce13f7SAndroid Build Coastguard Worker
105*03ce13f7SAndroid Build Coastguard WorkerThe translation thread destroys the Cfg when it is done translating, including
106*03ce13f7SAndroid Build Coastguard Workerthe Cfg's slab allocator, and clears the allocator pointer from its TLS.
107*03ce13f7SAndroid Build Coastguard WorkerLikewise, the writer thread destroys the assembler buffer when it is finished
108*03ce13f7SAndroid Build Coastguard Workerwith it.
109*03ce13f7SAndroid Build Coastguard Worker
110*03ce13f7SAndroid Build Coastguard WorkerThread safety
111*03ce13f7SAndroid Build Coastguard Worker-------------
112*03ce13f7SAndroid Build Coastguard Worker
113*03ce13f7SAndroid Build Coastguard WorkerThe parse/translate/write stages of the translation pipeline are fairly
114*03ce13f7SAndroid Build Coastguard Workerindependent, with little opportunity for threads to interfere.  The Subzero
115*03ce13f7SAndroid Build Coastguard Workerdesign calls for all shared accesses to go through the GlobalContext, which adds
116*03ce13f7SAndroid Build Coastguard Workerlocking as appropriate.  This includes the coarse-grain work queues for Cfgs and
117*03ce13f7SAndroid Build Coastguard Workerassembler buffers.  It also includes finer-grain access to constant pool
118*03ce13f7SAndroid Build Coastguard Workerentries, as well as output streams for verbose debugging output.
119*03ce13f7SAndroid Build Coastguard Worker
120*03ce13f7SAndroid Build Coastguard WorkerIf locked access to constant pools becomes a bottleneck, we can investigate
121*03ce13f7SAndroid Build Coastguard Workerthread-local caches of constants (as mentioned earlier).  Also, it should be
122*03ce13f7SAndroid Build Coastguard Workersafe though slightly less efficient to allow duplicate copies of constants
123*03ce13f7SAndroid Build Coastguard Workeracross threads (which could be de-dupped by the writer at the end).
124*03ce13f7SAndroid Build Coastguard Worker
125*03ce13f7SAndroid Build Coastguard WorkerWe will use ThreadSanitizer as a way to detect potential data races in the
126*03ce13f7SAndroid Build Coastguard Workerimplementation.
127