Skip to content

Commit efc7ff5

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 7d57ce4 + 6399016 commit efc7ff5

File tree

1 file changed

+118
-116
lines changed

1 file changed

+118
-116
lines changed

include/swift/Basic/RelativePointer.h

Lines changed: 118 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -9,122 +9,124 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
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+
///
128130
//===----------------------------------------------------------------------===//
129131

130132
#ifndef SWIFT_BASIC_RELATIVEPOINTER_H

0 commit comments

Comments
 (0)