17
17
// unnecessary relocation at dynamic linking time. This header contains types
18
18
// to help dereference these relative addresses.
19
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 desireable 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
- //
128
20
// ===----------------------------------------------------------------------===//
129
21
130
22
#ifndef SWIFT_BASIC_RELATIVEPOINTER_H
@@ -387,8 +279,7 @@ class RelativeDirectPointer<RetTy (ArgTy...), Nullable, Offset> :
387
279
388
280
// / A direct relative reference to an aligned object, with an additional
389
281
// / tiny integer value crammed into its low bits.
390
- template <typename PointeeTy, typename IntTy, bool Nullable = false ,
391
- typename Offset = int32_t >
282
+ template <typename PointeeTy, typename IntTy, typename Offset = int32_t >
392
283
class RelativeDirectPointerIntPair {
393
284
Offset RelativeOffsetPlusInt;
394
285
@@ -414,14 +305,9 @@ class RelativeDirectPointerIntPair {
414
305
using PointerTy = PointeeTy*;
415
306
416
307
PointerTy getPointer () const & {
417
- Offset offset = (RelativeOffsetPlusInt & ~getMask ());
418
-
419
- // Check for null.
420
- if (Nullable && offset == 0 )
421
- return nullptr ;
422
-
423
308
// The value is addressed relative to `this`.
424
- uintptr_t absolute = detail::applyRelativeOffset (this , offset);
309
+ uintptr_t absolute = detail::applyRelativeOffset (this ,
310
+ RelativeOffsetPlusInt & ~getMask ());
425
311
return reinterpret_cast <PointerTy>(absolute);
426
312
}
427
313
0 commit comments