@@ -42,11 +42,19 @@ extern "C" {
42
42
// TODO: the stack probably needs to be artificially large because of some
43
43
// deeper problem (see #21191) and could be shrunk once that is fixed
44
44
typedef struct {
45
- int depth ;
46
- int more ;
45
+ int16_t depth ;
46
+ int16_t more ;
47
+ int16_t used ;
47
48
uint32_t stack [100 ]; // stack of bits represented as a bit vector
48
49
} jl_unionstate_t ;
49
50
51
+ typedef struct {
52
+ int16_t depth ;
53
+ int16_t more ;
54
+ int16_t used ;
55
+ void * stack ;
56
+ } jl_saved_unionstate_t ;
57
+
50
58
// Linked list storing the type variable environment. A new jl_varbinding_t
51
59
// is pushed for each UnionAll type we encounter. `lb` and `ub` are updated
52
60
// during the computation.
@@ -68,14 +76,14 @@ typedef struct jl_varbinding_t {
68
76
// and we would need to return `intersect(var,other)`. in this case
69
77
// we choose to over-estimate the intersection by returning the var.
70
78
int8_t constraintkind ;
71
- int depth0 ; // # of invariant constructors nested around the UnionAll type for this var
79
+ int8_t intvalued ; // must be integer-valued; i.e. occurs as N in Vararg{_,N}
80
+ int16_t depth0 ; // # of invariant constructors nested around the UnionAll type for this var
72
81
// when this variable's integer value is compared to that of another,
73
82
// it equals `other + offset`. used by vararg length parameters.
74
- int offset ;
83
+ int16_t offset ;
75
84
// array of typevars that our bounds depend on, whose UnionAlls need to be
76
85
// moved outside ours.
77
86
jl_array_t * innervars ;
78
- int intvalued ; // must be integer-valued; i.e. occurs as N in Vararg{_,N}
79
87
struct jl_varbinding_t * prev ;
80
88
} jl_varbinding_t ;
81
89
@@ -129,6 +137,23 @@ static void statestack_set(jl_unionstate_t *st, int i, int val) JL_NOTSAFEPOINT
129
137
st -> stack [i >>5 ] &= ~(1u <<(i & 31 ));
130
138
}
131
139
140
+ #define push_unionstate (saved , src ) \
141
+ do { \
142
+ (saved)->depth = (src)->depth; \
143
+ (saved)->more = (src)->more; \
144
+ (saved)->used = (src)->used; \
145
+ (saved)->stack = alloca(((src)->used+7)/8); \
146
+ memcpy((saved)->stack, &(src)->stack, ((src)->used+7)/8); \
147
+ } while (0);
148
+
149
+ #define pop_unionstate (dst , saved ) \
150
+ do { \
151
+ (dst)->depth = (saved)->depth; \
152
+ (dst)->more = (saved)->more; \
153
+ (dst)->used = (saved)->used; \
154
+ memcpy(&(dst)->stack, (saved)->stack, ((saved)->used+7)/8); \
155
+ } while (0);
156
+
132
157
typedef struct {
133
158
int8_t * buf ;
134
159
int rdepth ;
@@ -486,6 +511,10 @@ static jl_value_t *pick_union_element(jl_value_t *u JL_PROPAGATES_ROOT, jl_stenv
486
511
{
487
512
jl_unionstate_t * state = R ? & e -> Runions : & e -> Lunions ;
488
513
do {
514
+ if (state -> depth >= state -> used ) {
515
+ statestack_set (state , state -> used , 0 );
516
+ state -> used ++ ;
517
+ }
489
518
int ui = statestack_get (state , state -> depth );
490
519
state -> depth ++ ;
491
520
if (ui == 0 ) {
@@ -514,20 +543,19 @@ static int subtype_ccheck(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
514
543
return 1 ;
515
544
if (x == (jl_value_t * )jl_any_type && jl_is_datatype (y ))
516
545
return 0 ;
517
- jl_unionstate_t oldLunions = e -> Lunions ;
518
- jl_unionstate_t oldRunions = e -> Runions ;
546
+ jl_saved_unionstate_t oldLunions ; push_unionstate ( & oldLunions , & e -> Lunions ) ;
547
+ jl_saved_unionstate_t oldRunions ; push_unionstate ( & oldRunions , & e -> Runions ) ;
519
548
int sub ;
520
- memset (e -> Lunions .stack , 0 , sizeof (e -> Lunions .stack ));
521
- memset (e -> Runions .stack , 0 , sizeof (e -> Runions .stack ));
549
+ e -> Lunions .used = e -> Runions .used = 0 ;
522
550
e -> Runions .depth = 0 ;
523
551
e -> Runions .more = 0 ;
524
552
e -> Lunions .depth = 0 ;
525
553
e -> Lunions .more = 0 ;
526
554
527
555
sub = forall_exists_subtype (x , y , e , 0 );
528
556
529
- e -> Runions = oldRunions ;
530
- e -> Lunions = oldLunions ;
557
+ pop_unionstate ( & e -> Runions , & oldRunions ) ;
558
+ pop_unionstate ( & e -> Lunions , & oldLunions ) ;
531
559
return sub ;
532
560
}
533
561
@@ -731,8 +759,8 @@ static jl_unionall_t *unalias_unionall(jl_unionall_t *u, jl_stenv_t *e)
731
759
static int subtype_unionall (jl_value_t * t , jl_unionall_t * u , jl_stenv_t * e , int8_t R , int param )
732
760
{
733
761
u = unalias_unionall (u , e );
734
- jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , 0 , 0 , 0 , 0 ,
735
- R ? e -> Rinvdepth : e -> invdepth , 0 , NULL , 0 , e -> vars };
762
+ jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , 0 , 0 , 0 , 0 , 0 ,
763
+ R ? e -> Rinvdepth : e -> invdepth , 0 , NULL , e -> vars };
736
764
JL_GC_PUSH4 (& u , & vb .lb , & vb .ub , & vb .innervars );
737
765
e -> vars = & vb ;
738
766
int ans ;
@@ -1148,6 +1176,10 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
1148
1176
// union against the variable before trying to take it apart to see if there are any
1149
1177
// variables lurking inside.
1150
1178
jl_unionstate_t * state = & e -> Runions ;
1179
+ if (state -> depth >= state -> used ) {
1180
+ statestack_set (state , state -> used , 0 );
1181
+ state -> used ++ ;
1182
+ }
1151
1183
ui = statestack_get (state , state -> depth );
1152
1184
state -> depth ++ ;
1153
1185
if (ui == 0 )
@@ -1310,21 +1342,21 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
1310
1342
(is_definite_length_tuple_type (x ) && is_indefinite_length_tuple_type (y )))
1311
1343
return 0 ;
1312
1344
1313
- jl_unionstate_t oldLunions = e -> Lunions ;
1314
- memset ( e -> Lunions .stack , 0 , sizeof ( e -> Lunions . stack )) ;
1345
+ jl_saved_unionstate_t oldLunions ; push_unionstate ( & oldLunions , & e -> Lunions ) ;
1346
+ e -> Lunions .used = 0 ;
1315
1347
int sub ;
1316
1348
1317
1349
if (!jl_has_free_typevars (x ) || !jl_has_free_typevars (y )) {
1318
- jl_unionstate_t oldRunions = e -> Runions ;
1319
- memset ( e -> Runions .stack , 0 , sizeof ( e -> Runions . stack )) ;
1350
+ jl_saved_unionstate_t oldRunions ; push_unionstate ( & oldRunions , & e -> Runions ) ;
1351
+ e -> Runions .used = 0 ;
1320
1352
e -> Runions .depth = 0 ;
1321
1353
e -> Runions .more = 0 ;
1322
1354
e -> Lunions .depth = 0 ;
1323
1355
e -> Lunions .more = 0 ;
1324
1356
1325
1357
sub = forall_exists_subtype (x , y , e , 2 );
1326
1358
1327
- e -> Runions = oldRunions ;
1359
+ pop_unionstate ( & e -> Runions , & oldRunions ) ;
1328
1360
}
1329
1361
else {
1330
1362
int lastset = 0 ;
@@ -1342,13 +1374,13 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
1342
1374
}
1343
1375
}
1344
1376
1345
- e -> Lunions = oldLunions ;
1377
+ pop_unionstate ( & e -> Lunions , & oldLunions ) ;
1346
1378
return sub && subtype (y , x , e , 0 );
1347
1379
}
1348
1380
1349
1381
static int exists_subtype (jl_value_t * x , jl_value_t * y , jl_stenv_t * e , jl_value_t * saved , jl_savedenv_t * se , int param )
1350
1382
{
1351
- memset ( e -> Runions .stack , 0 , sizeof ( e -> Runions . stack )) ;
1383
+ e -> Runions .used = 0 ;
1352
1384
int lastset = 0 ;
1353
1385
while (1 ) {
1354
1386
e -> Runions .depth = 0 ;
@@ -1379,7 +1411,7 @@ static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, in
1379
1411
JL_GC_PUSH1 (& saved );
1380
1412
save_env (e , & saved , & se );
1381
1413
1382
- memset ( e -> Lunions .stack , 0 , sizeof ( e -> Lunions . stack )) ;
1414
+ e -> Lunions .used = 0 ;
1383
1415
int lastset = 0 ;
1384
1416
int sub ;
1385
1417
while (1 ) {
@@ -1415,6 +1447,7 @@ static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz)
1415
1447
e -> emptiness_only = 0 ;
1416
1448
e -> Lunions .depth = 0 ; e -> Runions .depth = 0 ;
1417
1449
e -> Lunions .more = 0 ; e -> Runions .more = 0 ;
1450
+ e -> Lunions .used = 0 ; e -> Runions .used = 0 ;
1418
1451
}
1419
1452
1420
1453
// subtyping entry points
@@ -2084,14 +2117,14 @@ static jl_value_t *intersect_aside(jl_value_t *x, jl_value_t *y, jl_stenv_t *e,
2084
2117
if (y == (jl_value_t * )jl_any_type && !jl_is_typevar (x ))
2085
2118
return x ;
2086
2119
2087
- jl_unionstate_t oldRunions = e -> Runions ;
2120
+ jl_saved_unionstate_t oldRunions ; push_unionstate ( & oldRunions , & e -> Runions ) ;
2088
2121
int savedepth = e -> invdepth , Rsavedepth = e -> Rinvdepth ;
2089
2122
// TODO: this doesn't quite make sense
2090
2123
e -> invdepth = e -> Rinvdepth = d ;
2091
2124
2092
2125
jl_value_t * res = intersect_all (x , y , e );
2093
2126
2094
- e -> Runions = oldRunions ;
2127
+ pop_unionstate ( & e -> Runions , & oldRunions ) ;
2095
2128
e -> invdepth = savedepth ;
2096
2129
e -> Rinvdepth = Rsavedepth ;
2097
2130
return res ;
@@ -2102,10 +2135,10 @@ static jl_value_t *intersect_union(jl_value_t *x, jl_uniontype_t *u, jl_stenv_t
2102
2135
if (param == 2 || (!jl_has_free_typevars (x ) && !jl_has_free_typevars ((jl_value_t * )u ))) {
2103
2136
jl_value_t * a = NULL , * b = NULL ;
2104
2137
JL_GC_PUSH2 (& a , & b );
2105
- jl_unionstate_t oldRunions = e -> Runions ;
2138
+ jl_saved_unionstate_t oldRunions ; push_unionstate ( & oldRunions , & e -> Runions ) ;
2106
2139
a = R ? intersect_all (x , u -> a , e ) : intersect_all (u -> a , x , e );
2107
2140
b = R ? intersect_all (x , u -> b , e ) : intersect_all (u -> b , x , e );
2108
- e -> Runions = oldRunions ;
2141
+ pop_unionstate ( & e -> Runions , & oldRunions ) ;
2109
2142
jl_value_t * i = simple_join (a ,b );
2110
2143
JL_GC_POP ();
2111
2144
return i ;
@@ -2600,8 +2633,8 @@ static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_
2600
2633
{
2601
2634
jl_value_t * res = NULL , * res2 = NULL , * save = NULL , * save2 = NULL ;
2602
2635
jl_savedenv_t se , se2 ;
2603
- jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , 0 , 0 , 0 , 0 ,
2604
- R ? e -> Rinvdepth : e -> invdepth , 0 , NULL , 0 , e -> vars };
2636
+ jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , 0 , 0 , 0 , 0 , 0 ,
2637
+ R ? e -> Rinvdepth : e -> invdepth , 0 , NULL , e -> vars };
2605
2638
JL_GC_PUSH6 (& res , & save2 , & vb .lb , & vb .ub , & save , & vb .innervars );
2606
2639
save_env (e , & save , & se );
2607
2640
res = intersect_unionall_ (t , u , e , R , param , & vb );
@@ -3159,7 +3192,7 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
3159
3192
{
3160
3193
e -> Runions .depth = 0 ;
3161
3194
e -> Runions .more = 0 ;
3162
- memset ( e -> Runions .stack , 0 , sizeof ( e -> Runions . stack )) ;
3195
+ e -> Runions .used = 0 ;
3163
3196
jl_value_t * * is ;
3164
3197
JL_GC_PUSHARGS (is , 3 );
3165
3198
jl_value_t * * saved = & is [2 ];
@@ -3176,11 +3209,8 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
3176
3209
save_env (e , saved , & se );
3177
3210
}
3178
3211
while (e -> Runions .more ) {
3179
- if (e -> emptiness_only && ii != jl_bottom_type ) {
3180
- free_env (& se );
3181
- JL_GC_POP ();
3182
- return ii ;
3183
- }
3212
+ if (e -> emptiness_only && ii != jl_bottom_type )
3213
+ break ;
3184
3214
e -> Runions .depth = 0 ;
3185
3215
int set = e -> Runions .more - 1 ;
3186
3216
e -> Runions .more = 0 ;
@@ -3209,9 +3239,8 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
3209
3239
}
3210
3240
total_iter ++ ;
3211
3241
if (niter > 3 || total_iter > 400000 ) {
3212
- free_env (& se );
3213
- JL_GC_POP ();
3214
- return y ;
3242
+ ii = y ;
3243
+ break ;
3215
3244
}
3216
3245
}
3217
3246
free_env (& se );
0 commit comments