@@ -151,8 +151,67 @@ impl<D: rustc_serialize::Decoder> FingerprintDecoder for D {
151151 panic ! ( "Cannot decode `Fingerprint` with `{}`" , std:: any:: type_name:: <D >( ) ) ;
152152 }
153153}
154+
154155impl FingerprintDecoder for opaque:: Decoder < ' _ > {
155156 fn decode_fingerprint ( & mut self ) -> Result < Fingerprint , String > {
156157 Fingerprint :: decode_opaque ( self )
157158 }
158159}
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