@@ -151,8 +151,67 @@ impl<D: rustc_serialize::Decoder> FingerprintDecoder for D {
151
151
panic ! ( "Cannot decode `Fingerprint` with `{}`" , std:: any:: type_name:: <D >( ) ) ;
152
152
}
153
153
}
154
+
154
155
impl FingerprintDecoder for opaque:: Decoder < ' _ > {
155
156
fn decode_fingerprint ( & mut self ) -> Result < Fingerprint , String > {
156
157
Fingerprint :: decode_opaque ( self )
157
158
}
158
159
}
160
+
161
+ // `PackedFingerprint` wraps a `Fingerprint`. Its purpose is to, on certain
162
+ // architectures, behave like a `Fingerprint` without alignment requirements.
163
+ // This behavior is only enabled on x86 and x86_64, where the impact of
164
+ // unaligned accesses is tolerable in small doses.
165
+ //
166
+ // This may be preferable to use in large collections of structs containing
167
+ // fingerprints, as it can reduce memory consumption by preventing the padding
168
+ // that the more strictly-aligned `Fingerprint` can introduce. An application of
169
+ // this is in the query dependency graph, which contains a large collection of
170
+ // `DepNode`s. As of this writing, the size of a `DepNode` decreases by ~30%
171
+ // (from 24 bytes to 17) by using the packed representation here, which
172
+ // noticeably decreases total memory usage when compiling large crates.
173
+ //
174
+ // The wrapped `Fingerprint` is private to reduce the chance of a client
175
+ // invoking undefined behavior by taking a reference to the packed field.
176
+ #[ cfg_attr( any( target_arch = "x86" , target_arch = "x86_64" ) , repr( packed) ) ]
177
+ #[ derive( Eq , PartialEq , Ord , PartialOrd , Debug , Clone , Copy , Hash ) ]
178
+ pub struct PackedFingerprint ( Fingerprint ) ;
179
+
180
+ impl std:: fmt:: Display for PackedFingerprint {
181
+ #[ inline]
182
+ fn fmt ( & self , formatter : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
183
+ // Copy to avoid taking reference to packed field.
184
+ let copy = self . 0 ;
185
+ copy. fmt ( formatter)
186
+ }
187
+ }
188
+
189
+ impl < E : rustc_serialize:: Encoder > Encodable < E > for PackedFingerprint {
190
+ #[ inline]
191
+ fn encode ( & self , s : & mut E ) -> Result < ( ) , E :: Error > {
192
+ // Copy to avoid taking reference to packed field.
193
+ let copy = self . 0 ;
194
+ copy. encode ( s)
195
+ }
196
+ }
197
+
198
+ impl < D : rustc_serialize:: Decoder > Decodable < D > for PackedFingerprint {
199
+ #[ inline]
200
+ fn decode ( d : & mut D ) -> Result < Self , D :: Error > {
201
+ Fingerprint :: decode ( d) . map ( |f| PackedFingerprint ( f) )
202
+ }
203
+ }
204
+
205
+ impl From < Fingerprint > for PackedFingerprint {
206
+ #[ inline]
207
+ fn from ( f : Fingerprint ) -> PackedFingerprint {
208
+ PackedFingerprint ( f)
209
+ }
210
+ }
211
+
212
+ impl From < PackedFingerprint > for Fingerprint {
213
+ #[ inline]
214
+ fn from ( f : PackedFingerprint ) -> Fingerprint {
215
+ f. 0
216
+ }
217
+ }
0 commit comments