|
9 | 9 | // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 |
| -// |
13 |
| -// Some data structures emitted by the Swift compiler use relative indirect |
14 |
| -// addresses in order to minimize startup cost for a process. By referring to |
15 |
| -// the offset of the global offset table entry for a symbol, instead of directly |
16 |
| -// referring to the symbol, compiler-emitted data structures avoid requiring |
17 |
| -// unnecessary relocation at dynamic linking time. This header contains types |
18 |
| -// to help dereference these relative addresses. |
19 |
| -// |
20 |
| -// Theory of references to objects |
21 |
| -// ------------------------------- |
22 |
| -// |
23 |
| -// A reference can be absolute or relative: |
24 |
| -// |
25 |
| -// - An absolute reference is a pointer to the object. |
26 |
| -// |
27 |
| -// - A relative reference is a (signed) offset from the address of the |
28 |
| -// reference to the address of its direct referent. |
29 |
| -// |
30 |
| -// A relative reference can be direct, indirect, or symbolic. |
31 |
| -// |
32 |
| -// In a direct reference, the direct referent is simply the target object. |
33 |
| -// Generally, a statically-emitted relative reference can only be direct |
34 |
| -// if it can be resolved to a constant offset by the linker, because loaders |
35 |
| -// do not support forming relative references. This means that either the |
36 |
| -// reference and object must lie within the same linkage unit or the |
37 |
| -// difference must be computed at runtime by code. |
38 |
| -// |
39 |
| -// In a symbolic reference, the direct referent is a string holding the symbol |
40 |
| -// name of the object. A relative reference can only be symbolic if the |
41 |
| -// object actually has a symbol at runtime, which may require exporting |
42 |
| -// many internal symbols that would otherwise be strippable. |
43 |
| -// |
44 |
| -// In an indirect reference, the direct referent is a variable holding an |
45 |
| -// absolute reference to the object. An indirect relative reference may |
46 |
| -// refer to an arbitrary symbol, be it anonymous within the linkage unit |
47 |
| -// or completely external to it, but it requires the introduction of an |
48 |
| -// intermediate absolute reference that requires load-time initialization. |
49 |
| -// However, this initialization can be shared among all indirect references |
50 |
| -// within the linkage unit, and the linker will generally place all such |
51 |
| -// references adjacent to one another to improve load-time locality. |
52 |
| -// |
53 |
| -// A reference can be made a dynamic union of more than one of these options. |
54 |
| -// This allows the compiler/linker to use a direct reference when possible |
55 |
| -// and a less-efficient option where required. However, it also requires |
56 |
| -// the cases to be dynamically distinguished. This can be done by setting |
57 |
| -// a low bit of the offset, as long as the difference between the direct |
58 |
| -// referent's address and the reference is a multiple of 2. This works well |
59 |
| -// for "indirectable" references because most objects are known to be |
60 |
| -// well-aligned, and the cases that aren't (chiefly functions and strings) |
61 |
| -// rarely need the flexibility of this kind of reference. It does not |
62 |
| -// work quite as well for "possibly symbolic" references because C strings |
63 |
| -// are not naturally aligned, and making them aligned generally requires |
64 |
| -// moving them out of the linker's ordinary string section; however, it's |
65 |
| -// still workable. |
66 |
| -// |
67 |
| -// Finally, a relative reference can be near or far. A near reference |
68 |
| -// is potentially smaller, but it requires the direct referent to lie |
69 |
| -// within a certain distance of the reference, even if dynamically |
70 |
| -// initialized. |
71 |
| -// |
72 |
| -// In Swift, we always prefer to use a near direct relative reference |
73 |
| -// when it is possible to do so: that is, when the relationship is always |
74 |
| -// between two global objects emitted in the same linkage unit, and there |
75 |
| -// is no compatibility constraint requiring the use of an absolute reference. |
76 |
| -// |
77 |
| -// When more flexibility is required, there are several options: |
78 |
| -// |
79 |
| -// 1. Use an absolute reference. Size penalty on 64-bit. Requires |
80 |
| -// load-time work. |
81 |
| -// |
82 |
| -// 2. Use a far direct relative reference. Size penalty on 64-bit. |
83 |
| -// Requires load-time work when object is outside linkage unit. |
84 |
| -// Generally not directly supported by loaders. |
85 |
| -// |
86 |
| -// 3. Use an always-indirect relative reference. Size penalty of one |
87 |
| -// pointer (shared). Requires load-time work even when object is |
88 |
| -// within linkage unit. |
89 |
| -// |
90 |
| -// 4. Use a near indirectable relative reference. Size penalty of one |
91 |
| -// pointer (shared) when reference exceeds range. Runtime / code-size |
92 |
| -// penalty on access. Requires load-time work (shared) only when |
93 |
| -// object is outside linkage unit. |
94 |
| -// |
95 |
| -// 5. Use a far indirectable relative reference. Size penalty on 64-bit. |
96 |
| -// Size penalty of one pointer (shared) when reference exceeds range |
97 |
| -// and is initialized statically. Runtime / code-size penalty on access. |
98 |
| -// Requires load-time work (shared) only when object is outside linkage |
99 |
| -// unit. |
100 |
| -// |
101 |
| -// 6. Use a near or far symbolic relative reference. No load-time work. |
102 |
| -// Severe runtime penalty on access. Requires custom logic to statically |
103 |
| -// optimize. Requires emission of symbol for target even if private |
104 |
| -// to linkage unit. |
105 |
| -// |
106 |
| -// 7. Use a near or far direct-or-symbolic relative reference. No |
107 |
| -// load-time work. Severe runtime penalty on access if object is |
108 |
| -// outside of linkage unit. Requires custom logic to statically optimize. |
109 |
| -// |
110 |
| -// In general, it's our preference in Swift to use option #4 when there |
111 |
| -// is no possibility of initializing the reference dynamically and option #5 |
112 |
| -// when there is. This is because it is infeasible to actually share the |
113 |
| -// memory for the intermediate absolute reference when it must be allocated |
114 |
| -// dynamically. |
115 |
| -// |
116 |
| -// Symbolic references are an interesting idea that we have not yet made |
117 |
| -// use of. They may be acceptable in reflective metadata cases where it |
118 |
| -// is desirable to heavily bias towards never using the metadata. However, |
119 |
| -// they're only profitable if there wasn't any other indirect reference |
120 |
| -// to the target, and it is likely that their optimal use requires a more |
121 |
| -// intelligent toolchain from top to bottom. |
122 |
| -// |
123 |
| -// Note that the cost of load-time work also includes a binary-size penalty |
124 |
| -// to store the loader metadata necessary to perform that work. Therefore |
125 |
| -// it is better to avoid it even when there are dynamic optimizations in |
126 |
| -// place to skip the work itself. |
127 |
| -// |
| 12 | +/// |
| 13 | +/// \file |
| 14 | +/// |
| 15 | +/// Some data structures emitted by the Swift compiler use relative indirect |
| 16 | +/// addresses in order to minimize startup cost for a process. By referring to |
| 17 | +/// the offset of the global offset table entry for a symbol, instead of |
| 18 | +/// directly referring to the symbol, compiler-emitted data structures avoid |
| 19 | +/// requiring unnecessary relocation at dynamic linking time. This header |
| 20 | +/// contains types to help dereference these relative addresses. |
| 21 | +/// |
| 22 | +/// Theory of references to objects |
| 23 | +/// ------------------------------- |
| 24 | +/// |
| 25 | +/// A reference can be absolute or relative: |
| 26 | +/// |
| 27 | +/// - An absolute reference is a pointer to the object. |
| 28 | +/// |
| 29 | +/// - A relative reference is a (signed) offset from the address of the |
| 30 | +/// reference to the address of its direct referent. |
| 31 | +/// |
| 32 | +/// A relative reference can be direct, indirect, or symbolic. |
| 33 | +/// |
| 34 | +/// In a direct reference, the direct referent is simply the target object. |
| 35 | +/// Generally, a statically-emitted relative reference can only be direct |
| 36 | +/// if it can be resolved to a constant offset by the linker, because loaders |
| 37 | +/// do not support forming relative references. This means that either the |
| 38 | +/// reference and object must lie within the same linkage unit or the |
| 39 | +/// difference must be computed at runtime by code. |
| 40 | +/// |
| 41 | +/// In a symbolic reference, the direct referent is a string holding the symbol |
| 42 | +/// name of the object. A relative reference can only be symbolic if the |
| 43 | +/// object actually has a symbol at runtime, which may require exporting |
| 44 | +/// many internal symbols that would otherwise be strippable. |
| 45 | +/// |
| 46 | +/// In an indirect reference, the direct referent is a variable holding an |
| 47 | +/// absolute reference to the object. An indirect relative reference may |
| 48 | +/// refer to an arbitrary symbol, be it anonymous within the linkage unit |
| 49 | +/// or completely external to it, but it requires the introduction of an |
| 50 | +/// intermediate absolute reference that requires load-time initialization. |
| 51 | +/// However, this initialization can be shared among all indirect references |
| 52 | +/// within the linkage unit, and the linker will generally place all such |
| 53 | +/// references adjacent to one another to improve load-time locality. |
| 54 | +/// |
| 55 | +/// A reference can be made a dynamic union of more than one of these options. |
| 56 | +/// This allows the compiler/linker to use a direct reference when possible |
| 57 | +/// and a less-efficient option where required. However, it also requires |
| 58 | +/// the cases to be dynamically distinguished. This can be done by setting |
| 59 | +/// a low bit of the offset, as long as the difference between the direct |
| 60 | +/// referent's address and the reference is a multiple of 2. This works well |
| 61 | +/// for "indirectable" references because most objects are known to be |
| 62 | +/// well-aligned, and the cases that aren't (chiefly functions and strings) |
| 63 | +/// rarely need the flexibility of this kind of reference. It does not |
| 64 | +/// work quite as well for "possibly symbolic" references because C strings |
| 65 | +/// are not naturally aligned, and making them aligned generally requires |
| 66 | +/// moving them out of the linker's ordinary string section; however, it's |
| 67 | +/// still workable. |
| 68 | +/// |
| 69 | +/// Finally, a relative reference can be near or far. A near reference |
| 70 | +/// is potentially smaller, but it requires the direct referent to lie |
| 71 | +/// within a certain distance of the reference, even if dynamically |
| 72 | +/// initialized. |
| 73 | +/// |
| 74 | +/// In Swift, we always prefer to use a near direct relative reference |
| 75 | +/// when it is possible to do so: that is, when the relationship is always |
| 76 | +/// between two global objects emitted in the same linkage unit, and there |
| 77 | +/// is no compatibility constraint requiring the use of an absolute reference. |
| 78 | +/// |
| 79 | +/// When more flexibility is required, there are several options: |
| 80 | +/// |
| 81 | +/// 1. Use an absolute reference. Size penalty on 64-bit. Requires |
| 82 | +/// load-time work. |
| 83 | +/// |
| 84 | +/// 2. Use a far direct relative reference. Size penalty on 64-bit. |
| 85 | +/// Requires load-time work when object is outside linkage unit. |
| 86 | +/// Generally not directly supported by loaders. |
| 87 | +/// |
| 88 | +/// 3. Use an always-indirect relative reference. Size penalty of one |
| 89 | +/// pointer (shared). Requires load-time work even when object is |
| 90 | +/// within linkage unit. |
| 91 | +/// |
| 92 | +/// 4. Use a near indirectable relative reference. Size penalty of one |
| 93 | +/// pointer (shared) when reference exceeds range. Runtime / code-size |
| 94 | +/// penalty on access. Requires load-time work (shared) only when |
| 95 | +/// object is outside linkage unit. |
| 96 | +/// |
| 97 | +/// 5. Use a far indirectable relative reference. Size penalty on 64-bit. |
| 98 | +/// Size penalty of one pointer (shared) when reference exceeds range |
| 99 | +/// and is initialized statically. Runtime / code-size penalty on access. |
| 100 | +/// Requires load-time work (shared) only when object is outside linkage |
| 101 | +/// unit. |
| 102 | +/// |
| 103 | +/// 6. Use a near or far symbolic relative reference. No load-time work. |
| 104 | +/// Severe runtime penalty on access. Requires custom logic to statically |
| 105 | +/// optimize. Requires emission of symbol for target even if private |
| 106 | +/// to linkage unit. |
| 107 | +/// |
| 108 | +/// 7. Use a near or far direct-or-symbolic relative reference. No |
| 109 | +/// load-time work. Severe runtime penalty on access if object is |
| 110 | +/// outside of linkage unit. Requires custom logic to statically optimize. |
| 111 | +/// |
| 112 | +/// In general, it's our preference in Swift to use option #4 when there |
| 113 | +/// is no possibility of initializing the reference dynamically and option #5 |
| 114 | +/// when there is. This is because it is infeasible to actually share the |
| 115 | +/// memory for the intermediate absolute reference when it must be allocated |
| 116 | +/// dynamically. |
| 117 | +/// |
| 118 | +/// Symbolic references are an interesting idea that we have not yet made |
| 119 | +/// use of. They may be acceptable in reflective metadata cases where it |
| 120 | +/// is desirable to heavily bias towards never using the metadata. However, |
| 121 | +/// they're only profitable if there wasn't any other indirect reference |
| 122 | +/// to the target, and it is likely that their optimal use requires a more |
| 123 | +/// intelligent toolchain from top to bottom. |
| 124 | +/// |
| 125 | +/// Note that the cost of load-time work also includes a binary-size penalty |
| 126 | +/// to store the loader metadata necessary to perform that work. Therefore |
| 127 | +/// it is better to avoid it even when there are dynamic optimizations in |
| 128 | +/// place to skip the work itself. |
| 129 | +/// |
128 | 130 | //===----------------------------------------------------------------------===//
|
129 | 131 |
|
130 | 132 | #ifndef SWIFT_BASIC_RELATIVEPOINTER_H
|
|
0 commit comments