@@ -66,6 +66,10 @@ pub struct Module {
66
66
/// Whether we should encode a types section, even if `self.types` is empty.
67
67
should_encode_types : bool ,
68
68
69
+ /// Whether we should propagate sharedness to types generated inside
70
+ /// `propagate_shared`.
71
+ must_share : bool ,
72
+
69
73
/// All of this module's imports. These don't have their own index space,
70
74
/// but instead introduce entries to each imported entity's associated index
71
75
/// space.
@@ -246,6 +250,7 @@ impl Module {
246
250
max_type_limit : MaxTypeLimit :: ModuleTypes ,
247
251
interesting_values32 : Vec :: new ( ) ,
248
252
interesting_values64 : Vec :: new ( ) ,
253
+ must_share : false ,
249
254
}
250
255
}
251
256
}
@@ -680,8 +685,9 @@ impl Module {
680
685
fn arbitrary_sub_type ( & mut self , u : & mut Unstructured ) -> Result < SubType > {
681
686
if !self . config . gc_enabled {
682
687
let shared = self . arbitrary_shared ( u) ?;
688
+ let func_type = self . propagate_shared ( shared, |m| m. arbitrary_func_type ( u) ) ?;
683
689
let composite_type = CompositeType {
684
- inner : CompositeInnerType :: Func ( self . arbitrary_func_type ( u , shared ) ? ) ,
690
+ inner : CompositeInnerType :: Func ( func_type ) ,
685
691
shared,
686
692
} ;
687
693
return Ok ( SubType {
@@ -715,7 +721,9 @@ impl Module {
715
721
* f = self . arbitrary_matching_func_type ( u, f) ?;
716
722
}
717
723
CompositeInnerType :: Struct ( s) => {
718
- * s = self . arbitrary_matching_struct_type ( u, s, composite_type. shared ) ?;
724
+ * s = self . propagate_shared ( composite_type. shared , |m| {
725
+ m. arbitrary_matching_struct_type ( u, s)
726
+ } ) ?;
719
727
}
720
728
}
721
729
Ok ( SubType {
@@ -729,15 +737,14 @@ impl Module {
729
737
& mut self ,
730
738
u : & mut Unstructured ,
731
739
ty : & StructType ,
732
- must_share : bool ,
733
740
) -> Result < StructType > {
734
741
let len_extra_fields = u. int_in_range ( 0 ..=5 ) ?;
735
742
let mut fields = Vec :: with_capacity ( ty. fields . len ( ) + len_extra_fields) ;
736
743
for field in ty. fields . iter ( ) {
737
744
fields. push ( self . arbitrary_matching_field_type ( u, * field) ?) ;
738
745
}
739
746
for _ in 0 ..len_extra_fields {
740
- fields. push ( self . arbitrary_field_type ( u, must_share ) ?) ;
747
+ fields. push ( self . arbitrary_field_type ( u) ?) ;
741
748
}
742
749
Ok ( StructType {
743
750
fields : fields. into_boxed_slice ( ) ,
@@ -1024,85 +1031,75 @@ impl Module {
1024
1031
if !self . config . gc_enabled {
1025
1032
return Ok ( CompositeType {
1026
1033
shared,
1027
- inner : CT :: Func ( self . arbitrary_func_type ( u , shared ) ?) ,
1034
+ inner : CT :: Func ( self . propagate_shared ( shared , |m| m . arbitrary_func_type ( u ) ) ?) ,
1028
1035
} ) ;
1029
1036
}
1030
1037
1031
1038
match u. int_in_range ( 0 ..=2 ) ? {
1032
1039
0 => Ok ( CompositeType {
1033
1040
shared,
1034
- inner : CT :: Array ( ArrayType ( self . arbitrary_field_type ( u, shared) ?) ) ,
1041
+ inner : CT :: Array ( ArrayType (
1042
+ self . propagate_shared ( shared, |m| m. arbitrary_field_type ( u) ) ?,
1043
+ ) ) ,
1035
1044
} ) ,
1036
1045
1 => Ok ( CompositeType {
1037
1046
shared,
1038
- inner : CT :: Func ( self . arbitrary_func_type ( u , shared ) ?) ,
1047
+ inner : CT :: Func ( self . propagate_shared ( shared , |m| m . arbitrary_func_type ( u ) ) ?) ,
1039
1048
} ) ,
1040
1049
2 => Ok ( CompositeType {
1041
1050
shared,
1042
- inner : CT :: Struct ( self . arbitrary_struct_type ( u , shared ) ?) ,
1051
+ inner : CT :: Struct ( self . propagate_shared ( shared , |m| m . arbitrary_struct_type ( u ) ) ?) ,
1043
1052
} ) ,
1044
1053
_ => unreachable ! ( ) ,
1045
1054
}
1046
1055
}
1047
1056
1048
- fn arbitrary_struct_type (
1049
- & mut self ,
1050
- u : & mut Unstructured ,
1051
- must_share : bool ,
1052
- ) -> Result < StructType > {
1057
+ fn arbitrary_struct_type ( & mut self , u : & mut Unstructured ) -> Result < StructType > {
1053
1058
let len = u. int_in_range ( 0 ..=20 ) ?;
1054
1059
let mut fields = Vec :: with_capacity ( len) ;
1055
1060
for _ in 0 ..len {
1056
- fields. push ( self . arbitrary_field_type ( u, must_share ) ?) ;
1061
+ fields. push ( self . arbitrary_field_type ( u) ?) ;
1057
1062
}
1058
1063
Ok ( StructType {
1059
1064
fields : fields. into_boxed_slice ( ) ,
1060
1065
} )
1061
1066
}
1062
1067
1063
- fn arbitrary_field_type (
1064
- & mut self ,
1065
- u : & mut Unstructured ,
1066
- must_share : bool ,
1067
- ) -> Result < FieldType > {
1068
+ fn arbitrary_field_type ( & mut self , u : & mut Unstructured ) -> Result < FieldType > {
1068
1069
Ok ( FieldType {
1069
- element_type : self . arbitrary_storage_type ( u, must_share ) ?,
1070
+ element_type : self . arbitrary_storage_type ( u) ?,
1070
1071
mutable : u. arbitrary ( ) ?,
1071
1072
} )
1072
1073
}
1073
1074
1074
- fn arbitrary_storage_type (
1075
- & mut self ,
1076
- u : & mut Unstructured ,
1077
- must_share : bool ,
1078
- ) -> Result < StorageType > {
1075
+ fn arbitrary_storage_type ( & mut self , u : & mut Unstructured ) -> Result < StorageType > {
1079
1076
match u. int_in_range ( 0 ..=2 ) ? {
1080
1077
0 => Ok ( StorageType :: I8 ) ,
1081
1078
1 => Ok ( StorageType :: I16 ) ,
1082
- 2 => Ok ( StorageType :: Val ( self . arbitrary_valtype ( u, must_share ) ?) ) ,
1079
+ 2 => Ok ( StorageType :: Val ( self . arbitrary_valtype ( u) ?) ) ,
1083
1080
_ => unreachable ! ( ) ,
1084
1081
}
1085
1082
}
1086
1083
1087
- fn arbitrary_ref_type ( & self , u : & mut Unstructured , must_share : bool ) -> Result < RefType > {
1084
+ fn arbitrary_ref_type ( & self , u : & mut Unstructured ) -> Result < RefType > {
1088
1085
if !self . config . reference_types_enabled {
1089
1086
// Create a `RefType::FUNCREF` but with variable sharedness.
1090
1087
Ok ( RefType {
1091
1088
nullable : true ,
1092
1089
heap_type : HeapType :: Abstract {
1093
- shared : must_share ,
1090
+ shared : self . arbitrary_shared ( u ) ? ,
1094
1091
ty : AbstractHeapType :: Func ,
1095
1092
} ,
1096
1093
} )
1097
1094
} else {
1098
1095
Ok ( RefType {
1099
1096
nullable : true ,
1100
- heap_type : self . arbitrary_heap_type ( u, must_share ) ?,
1097
+ heap_type : self . arbitrary_heap_type ( u) ?,
1101
1098
} )
1102
1099
}
1103
1100
}
1104
1101
1105
- fn arbitrary_heap_type ( & self , u : & mut Unstructured , must_share : bool ) -> Result < HeapType > {
1102
+ fn arbitrary_heap_type ( & self , u : & mut Unstructured ) -> Result < HeapType > {
1106
1103
assert ! ( self . config. reference_types_enabled) ;
1107
1104
1108
1105
let concrete_type_limit = match self . max_type_limit {
@@ -1118,7 +1115,7 @@ impl Module {
1118
1115
// shared type, though, we can use either a shared or unshared
1119
1116
// concrete type.
1120
1117
if let Some ( ty) = self . types . get ( idx as usize ) {
1121
- if !( must_share && !ty. composite_type . shared ) {
1118
+ if !( self . must_share && !ty. composite_type . shared ) {
1122
1119
return Ok ( HeapType :: Concrete ( idx) ) ;
1123
1120
}
1124
1121
}
@@ -1138,21 +1135,17 @@ impl Module {
1138
1135
}
1139
1136
1140
1137
Ok ( HeapType :: Abstract {
1141
- shared : must_share || self . arbitrary_shared ( u) ?,
1138
+ shared : self . arbitrary_shared ( u) ?,
1142
1139
ty : * u. choose ( & choices) ?,
1143
1140
} )
1144
1141
}
1145
1142
1146
- fn arbitrary_func_type (
1147
- & mut self ,
1148
- u : & mut Unstructured ,
1149
- must_share : bool ,
1150
- ) -> Result < Rc < FuncType > > {
1143
+ fn arbitrary_func_type ( & mut self , u : & mut Unstructured ) -> Result < Rc < FuncType > > {
1151
1144
let mut params = vec ! [ ] ;
1152
1145
let mut results = vec ! [ ] ;
1153
1146
let max_params = 20 ;
1154
1147
arbitrary_loop ( u, 0 , max_params, |u| {
1155
- params. push ( self . arbitrary_valtype ( u, must_share ) ?) ;
1148
+ params. push ( self . arbitrary_valtype ( u) ?) ;
1156
1149
Ok ( true )
1157
1150
} ) ?;
1158
1151
let max_results = if self . config . multi_value_enabled {
@@ -1161,7 +1154,7 @@ impl Module {
1161
1154
1
1162
1155
} ;
1163
1156
arbitrary_loop ( u, 0 , max_results, |u| {
1164
- results. push ( self . arbitrary_valtype ( u, must_share ) ?) ;
1157
+ results. push ( self . arbitrary_valtype ( u) ?) ;
1165
1158
Ok ( true )
1166
1159
} ) ?;
1167
1160
Ok ( Rc :: new ( FuncType { params, results } ) )
@@ -1547,7 +1540,7 @@ impl Module {
1547
1540
. filter ( move |i| self . func_type ( * i) . results . is_empty ( ) )
1548
1541
}
1549
1542
1550
- fn arbitrary_valtype ( & self , u : & mut Unstructured , must_share : bool ) -> Result < ValType > {
1543
+ fn arbitrary_valtype ( & self , u : & mut Unstructured ) -> Result < ValType > {
1551
1544
#[ derive( PartialEq , Eq , PartialOrd , Ord ) ]
1552
1545
enum ValTypeClass {
1553
1546
I32 ,
@@ -1579,14 +1572,19 @@ impl Module {
1579
1572
ValTypeClass :: F32 => Ok ( ValType :: F32 ) ,
1580
1573
ValTypeClass :: F64 => Ok ( ValType :: F64 ) ,
1581
1574
ValTypeClass :: V128 => Ok ( ValType :: V128 ) ,
1582
- ValTypeClass :: Ref => Ok ( ValType :: Ref ( self . arbitrary_ref_type ( u, must_share ) ?) ) ,
1575
+ ValTypeClass :: Ref => Ok ( ValType :: Ref ( self . arbitrary_ref_type ( u) ?) ) ,
1583
1576
}
1584
1577
}
1585
1578
1586
1579
fn arbitrary_global_type ( & self , u : & mut Unstructured ) -> Result < GlobalType > {
1587
- let shared = self . arbitrary_shared ( u) ?;
1580
+ let val_type = self . arbitrary_valtype ( u) ?;
1581
+ // Propagate the inner type's sharedness to the global type.
1582
+ let shared = match val_type {
1583
+ ValType :: I32 | ValType :: I64 | ValType :: F32 | ValType :: F64 | ValType :: V128 => self . arbitrary_shared ( u) ?,
1584
+ ValType :: Ref ( r) => self . is_shared_ref_type ( r) ,
1585
+ } ;
1588
1586
Ok ( GlobalType {
1589
- val_type : self . arbitrary_valtype ( u , shared ) ? ,
1587
+ val_type,
1590
1588
mutable : u. arbitrary ( ) ?,
1591
1589
shared,
1592
1590
} )
@@ -2210,9 +2208,7 @@ impl Module {
2210
2208
// segment. Passive/declared segments can be declared with any
2211
2209
// reference type, but active segments must match their table.
2212
2210
let ty = match kind {
2213
- ElementKind :: Passive | ElementKind :: Declared => {
2214
- self . arbitrary_ref_type ( u, false ) ? // TODO: handle shared (no shared element types yet)
2215
- }
2211
+ ElementKind :: Passive | ElementKind :: Declared => self . arbitrary_ref_type ( u) ?,
2216
2212
ElementKind :: Active { table, .. } => {
2217
2213
let idx = table. unwrap_or ( 0 ) ;
2218
2214
self . arbitrary_matching_ref_type ( u, self . tables [ idx as usize ] . element_type ) ?
@@ -2318,8 +2314,7 @@ impl Module {
2318
2314
fn arbitrary_locals ( & self , u : & mut Unstructured ) -> Result < Vec < ValType > > {
2319
2315
let mut ret = Vec :: new ( ) ;
2320
2316
arbitrary_loop ( u, 0 , 100 , |u| {
2321
- let shared = self . arbitrary_shared ( u) ?;
2322
- ret. push ( self . arbitrary_valtype ( u, shared) ?) ;
2317
+ ret. push ( self . arbitrary_valtype ( u) ?) ;
2323
2318
Ok ( true )
2324
2319
} ) ?;
2325
2320
Ok ( ret)
@@ -2636,8 +2631,26 @@ impl Module {
2636
2631
}
2637
2632
}
2638
2633
2634
+ fn propagate_shared < T > ( & mut self , must_share : bool , mut f : impl FnMut ( & mut Self ) -> T ) -> T {
2635
+ let tmp = mem:: replace ( & mut self . must_share , must_share) ;
2636
+ let result = f ( self ) ;
2637
+ self . must_share = tmp;
2638
+ result
2639
+ }
2640
+
2639
2641
fn arbitrary_shared ( & self , u : & mut Unstructured ) -> Result < bool > {
2640
- Ok ( self . config . shared_everything_threads_enabled && u. ratio ( 1 , 4 ) ?)
2642
+ if self . must_share {
2643
+ Ok ( true )
2644
+ } else {
2645
+ Ok ( self . config . shared_everything_threads_enabled && u. ratio ( 1 , 4 ) ?)
2646
+ }
2647
+ }
2648
+
2649
+ fn is_shared_ref_type ( & self , ty : RefType ) -> bool {
2650
+ match ty. heap_type {
2651
+ HeapType :: Abstract { shared, .. } => shared,
2652
+ HeapType :: Concrete ( i) => self . types [ i as usize ] . composite_type . shared ,
2653
+ }
2641
2654
}
2642
2655
2643
2656
fn is_shared_type ( & self , index : u32 ) -> bool {
@@ -2744,12 +2757,17 @@ pub(crate) fn arbitrary_table_type(
2744
2757
if config. disallow_traps {
2745
2758
assert ! ( minimum > 0 ) ;
2746
2759
}
2747
- let shared = config. shared_everything_threads_enabled && u. arbitrary ( ) ?;
2748
2760
let element_type = match module {
2749
- Some ( module) => module. arbitrary_ref_type ( u, shared ) ?,
2761
+ Some ( module) => module. arbitrary_ref_type ( u) ?,
2750
2762
None => RefType :: FUNCREF ,
2751
2763
} ;
2752
2764
2765
+ // Propagate the element type's sharedness to the table type.
2766
+ let shared = match module {
2767
+ Some ( module) => module. is_shared_ref_type ( element_type) ,
2768
+ None => false ,
2769
+ } ;
2770
+
2753
2771
Ok ( TableType {
2754
2772
element_type,
2755
2773
minimum,
0 commit comments