@@ -17,6 +17,8 @@ use YuvImageDisplayItem;
17
17
use bincode;
18
18
use serde:: { Deserialize , Serialize , Serializer } ;
19
19
use serde:: ser:: { SerializeMap , SerializeSeq } ;
20
+ use std:: io:: Write ;
21
+ use std:: { io, ptr} ;
20
22
use std:: marker:: PhantomData ;
21
23
use time:: precise_time_ns;
22
24
@@ -483,6 +485,71 @@ impl<'a, 'b> Serialize for DisplayItemRef<'a, 'b> {
483
485
}
484
486
}
485
487
488
+ // This is a replacement for bincode::serialize_into(&vec)
489
+ // The default implementation Write for Vec will basically
490
+ // call extend_from_slice(). Serde ends up calling that for every
491
+ // field of a struct that we're serializing. extend_from_slice()
492
+ // does not get inlined and thus we end up calling a generic memcpy()
493
+ // implementation. If we instead reserve enough room for the serialized
494
+ // struct in the Vec ahead of time we can rely on that and use
495
+ // the following UnsafeVecWriter to write into the vec without
496
+ // any checks. This writer assumes that size returned by the
497
+ // serialize function will not change between calls to serialize_into:
498
+ //
499
+ // For example, the following struct will cause memory unsafety when
500
+ // used with UnsafeVecWriter.
501
+ //
502
+ // struct S {
503
+ // first: Cell<bool>,
504
+ // }
505
+ //
506
+ // impl Serialize for S {
507
+ // fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
508
+ // where S: Serializer
509
+ // {
510
+ // if self.first.get() {
511
+ // self.first.set(false);
512
+ // ().serialize(serializer)
513
+ // } else {
514
+ // 0.serialize(serializer)
515
+ // }
516
+ // }
517
+ // }
518
+ //
519
+
520
+ struct UnsafeVecWriter < ' a > ( & ' a mut Vec < u8 > ) ;
521
+
522
+ impl < ' a > Write for UnsafeVecWriter < ' a > {
523
+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
524
+ unsafe {
525
+ let old_len = self . 0 . len ( ) ;
526
+ self . 0 . set_len ( old_len + buf. len ( ) ) ;
527
+ ptr:: copy_nonoverlapping ( buf. as_ptr ( ) , self . 0 . as_mut_ptr ( ) . offset ( old_len as isize ) , buf. len ( ) ) ;
528
+ }
529
+ Ok ( buf. len ( ) )
530
+ }
531
+ fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
532
+ }
533
+
534
+ struct SizeCounter ( usize ) ;
535
+
536
+ impl < ' a > Write for SizeCounter {
537
+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
538
+ self . 0 += buf. len ( ) ;
539
+ Ok ( buf. len ( ) )
540
+ }
541
+ fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
542
+ }
543
+
544
+ fn serialize_fast < T : Serialize > ( vec : & mut Vec < u8 > , e : & T ) {
545
+ // manually counting the size is faster than vec.reserve(bincode::serialized_size(&e) as usize) for some reason
546
+ let mut size = SizeCounter ( 0 ) ;
547
+ bincode:: serialize_into ( & mut size, e , bincode:: Infinite ) . unwrap ( ) ;
548
+ vec. reserve ( size. 0 ) ;
549
+
550
+ bincode:: serialize_into ( & mut UnsafeVecWriter ( vec) , e, bincode:: Infinite ) . unwrap ( ) ;
551
+ }
552
+
486
553
#[ derive( Clone ) ]
487
554
pub struct DisplayListBuilder {
488
555
pub data : Vec < u8 > ,
@@ -541,28 +608,26 @@ impl DisplayListBuilder {
541
608
}
542
609
543
610
fn push_item ( & mut self , item : SpecificDisplayItem , info : & LayoutPrimitiveInfo ) {
544
- bincode :: serialize_into (
611
+ serialize_fast (
545
612
& mut self . data ,
546
613
& DisplayItem {
547
614
item,
548
615
clip_and_scroll : * self . clip_stack . last ( ) . unwrap ( ) ,
549
616
info : * info,
550
617
} ,
551
- bincode:: Infinite ,
552
- ) . unwrap ( ) ;
618
+ )
553
619
}
554
620
555
621
fn push_new_empty_item ( & mut self , item : SpecificDisplayItem ) {
556
622
let info = LayoutPrimitiveInfo :: new ( LayoutRect :: zero ( ) ) ;
557
- bincode :: serialize_into (
623
+ serialize_fast (
558
624
& mut self . data ,
559
625
& DisplayItem {
560
626
item,
561
627
clip_and_scroll : * self . clip_stack . last ( ) . unwrap ( ) ,
562
628
info,
563
- } ,
564
- bincode:: Infinite ,
565
- ) . unwrap ( ) ;
629
+ }
630
+ )
566
631
}
567
632
568
633
fn push_iter < I > ( & mut self , iter : I )
@@ -575,10 +640,10 @@ impl DisplayListBuilder {
575
640
let len = iter. len ( ) ;
576
641
let mut count = 0 ;
577
642
578
- bincode :: serialize_into ( & mut self . data , & len, bincode :: Infinite ) . unwrap ( ) ;
643
+ serialize_fast ( & mut self . data , & len) ;
579
644
for elem in iter {
580
645
count += 1 ;
581
- bincode :: serialize_into ( & mut self . data , & elem, bincode :: Infinite ) . unwrap ( ) ;
646
+ serialize_fast ( & mut self . data , & elem) ;
582
647
}
583
648
584
649
debug_assert_eq ! ( len, count) ;
@@ -1103,8 +1168,8 @@ impl DisplayListBuilder {
1103
1168
1104
1169
// Append glyph data to the end
1105
1170
for ( ( font_key, color) , sub_glyphs) in glyphs {
1106
- bincode :: serialize_into ( & mut self . data , & font_key, bincode :: Infinite ) . unwrap ( ) ;
1107
- bincode :: serialize_into ( & mut self . data , & color, bincode :: Infinite ) . unwrap ( ) ;
1171
+ serialize_fast ( & mut self . data , & font_key) ;
1172
+ serialize_fast ( & mut self . data , & color) ;
1108
1173
self . push_iter ( sub_glyphs) ;
1109
1174
}
1110
1175
0 commit comments