optimizer: repair unsafe-mutable-hash-iterate-next and similar

Related to #2685
This commit is contained in:
Matthew Flatt 2019-06-08 13:15:19 -06:00
parent b133bea92e
commit 07e35566e2
2 changed files with 33 additions and 28 deletions

View File

@ -3330,6 +3330,35 @@
'(lambda (x) 5)
#f))
(let ()
;; Although these are unsafe operations, they are obliged to
;; raise an exception if the iteration value used to be
;; ok and has become not ok due to a mutation (possibly
;; by the GC to drop a weakly held key)
(define (check-keep-iterate op-name)
(test-comp `(lambda (ht i) (,op-name ht i) 5)
`(lambda (ht i) 5)
#f))
(check-keep-iterate 'unsafe-mutable-hash-iterate-next)
(check-keep-iterate 'unsafe-weak-hash-iterate-next)
(check-keep-iterate 'unsafe-mutable-hash-iterate-key)
(check-keep-iterate 'unsafe-weak-hash-iterate-key)
(check-keep-iterate 'unsafe-mutable-hash-iterate-value)
(check-keep-iterate 'unsafe-weak-hash-iterate-value)
(check-keep-iterate 'unsafe-mutable-hash-iterate-key+value)
(check-keep-iterate 'unsafe-weak-hash-iterate-key+value)
(check-keep-iterate 'unsafe-mutable-hash-iterate-pair)
(check-keep-iterate 'unsafe-weak-hash-iterate-pair)
(define (check-discard-iterate op-name)
(test-comp `(lambda (ht i) (,op-name ht i) 5)
`(lambda (ht i) 5)))
(check-discard-iterate 'unsafe-immutable-hash-iterate-next)
(check-discard-iterate 'unsafe-immutable-hash-iterate-key)
(check-discard-iterate 'unsafe-immutable-hash-iterate-value)
(check-discard-iterate 'unsafe-immutable-hash-iterate-key+value)
(check-discard-iterate 'unsafe-immutable-hash-iterate-pair))
;; Check elimination of ignored structure predicate
;; and constructor applications:

View File

@ -967,11 +967,13 @@ scheme_init_unsafe_hash (Scheme_Startup_Env *env)
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL);
scheme_addto_prim_instance ("unsafe-weak-hash-iterate-first", p, env);
/* For the rest, only immutable variants can have
SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL, because a key can disappear
from mutable variants and trigger an error. */
/* unsafe-hash-iterate-next ---------------------------------------- */
p = scheme_make_immed_prim(unsafe_hash_table_iterate_next,
"unsafe-mutable-hash-iterate-next", 2, 2);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL);
scheme_addto_prim_instance ("unsafe-mutable-hash-iterate-next", p, env);
p = scheme_make_immed_prim(unsafe_hash_tree_iterate_next,
@ -982,16 +984,11 @@ scheme_init_unsafe_hash (Scheme_Startup_Env *env)
p = scheme_make_immed_prim(unsafe_bucket_table_iterate_next,
"unsafe-weak-hash-iterate-next", 2, 2);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL);
scheme_addto_prim_instance ("unsafe-weak-hash-iterate-next", p, env);
/* unsafe-hash-iterate-key ---------------------------------------- */
p = scheme_make_noncm_prim(unsafe_hash_table_iterate_key,
"unsafe-mutable-hash-iterate-key", 2, 3);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-mutable-hash-iterate-key", p, env);
p = scheme_make_noncm_prim(unsafe_hash_tree_iterate_key,
@ -1003,17 +1000,11 @@ scheme_init_unsafe_hash (Scheme_Startup_Env *env)
p = scheme_make_noncm_prim(unsafe_bucket_table_iterate_key,
"unsafe-weak-hash-iterate-key", 2, 3);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-weak-hash-iterate-key", p, env);
/* unsafe-hash-iterate-value ---------------------------------------- */
p = scheme_make_noncm_prim(unsafe_hash_table_iterate_value,
"unsafe-mutable-hash-iterate-value", 2, 3);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-mutable-hash-iterate-value", p, env);
p = scheme_make_noncm_prim(unsafe_hash_tree_iterate_value,
@ -1025,18 +1016,12 @@ scheme_init_unsafe_hash (Scheme_Startup_Env *env)
p = scheme_make_noncm_prim(unsafe_bucket_table_iterate_value,
"unsafe-weak-hash-iterate-value", 2, 3);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-weak-hash-iterate-value", p, env);
/* unsafe-hash-iterate-key+value ---------------------------------------- */
p = scheme_make_prim_w_arity2(unsafe_hash_table_iterate_key_value,
"unsafe-mutable-hash-iterate-key+value",
2, 3, 2, 2);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-mutable-hash-iterate-key+value", p, env);
p = scheme_make_prim_w_arity2(unsafe_hash_tree_iterate_key_value,
@ -1050,18 +1035,12 @@ scheme_init_unsafe_hash (Scheme_Startup_Env *env)
p = scheme_make_prim_w_arity2(unsafe_bucket_table_iterate_key_value,
"unsafe-weak-hash-iterate-key+value",
2, 3, 2, 2);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-weak-hash-iterate-key+value", p, env);
/* unsafe-hash-iterate-pair ---------------------------------------- */
p = scheme_make_immed_prim(unsafe_hash_table_iterate_pair,
"unsafe-mutable-hash-iterate-pair",
2, 3);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE_ALLOCATION
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-mutable-hash-iterate-pair", p, env);
p = scheme_make_immed_prim(unsafe_hash_tree_iterate_pair,
@ -1074,9 +1053,6 @@ scheme_init_unsafe_hash (Scheme_Startup_Env *env)
p = scheme_make_immed_prim(unsafe_bucket_table_iterate_pair,
"unsafe-weak-hash-iterate-pair",
2, 3);
SCHEME_PRIM_PROC_FLAGS(p) |=
scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_OMITABLE_ALLOCATION
| SCHEME_PRIM_IS_UNSAFE_OMITABLE);
scheme_addto_prim_instance ("unsafe-weak-hash-iterate-pair", p, env);
}