optimizer: recognize more struct declarations

The optimizer change in e887fa56d1 recognized struct declarations that
involved only whitelisted properties to guarantee that constructor
properties are preserved --- while `prop:chaperone-unsafe-undefined`
can affect the constructor, and other properties might imply that one.
But the optimizer's transformer aren't actually invalidated by
`prop:chaperone-unsafe-undefined`; the JIT's assumptions are affected,
but that's handled in a different way. So, remove the whitelist and
allow any property list.
This commit is contained in:
Matthew Flatt 2016-07-13 05:34:55 -06:00
parent bd28c4459d
commit 591fcb6228
2 changed files with 9 additions and 65 deletions

View File

@ -3978,18 +3978,6 @@
(a? (a-x (a 1 2)))
5)))
(test-comp '(module m racket/base
(require racket/unsafe/undefined)
(struct a (x y) #:omit-define-syntaxes
#:property prop:chaperone-unsafe-undefined '(y x))
(list (begin (a? 1) 2)))
'(module m racket/base
(require racket/unsafe/undefined)
(struct a (x y) #:omit-define-syntaxes
#:property prop:chaperone-unsafe-undefined '(y x))
(list 2))
#f)
(module struct-a-for-optimize racket/base
(provide (struct-out a)
(struct-out b))

View File

@ -1189,53 +1189,6 @@ static int is_constant_super(Scheme_Object *arg,
return 0;
}
static int is_simple_property_list(Scheme_Object *a, int resolved)
/* Does `a` produce a property list with no effect on the constructor? */
{
Scheme_Object *arg;
int i, count;
if (SAME_TYPE(SCHEME_TYPE(a), scheme_application_type))
count = ((Scheme_App_Rec *)a)->num_args;
else if (SAME_TYPE(SCHEME_TYPE(a), scheme_application2_type))
count = 1;
else if (SAME_TYPE(SCHEME_TYPE(a), scheme_application3_type))
count = 2;
else
return 0;
for (i = 0; i < count; i++) {
if (SAME_TYPE(SCHEME_TYPE(a), scheme_application_type))
arg = ((Scheme_App_Rec *)a)->args[i+1];
else if (SAME_TYPE(SCHEME_TYPE(a), scheme_application2_type))
arg = ((Scheme_App2_Rec *)a)->rator;
else {
if (i == 0)
arg = ((Scheme_App3_Rec *)a)->rand1;
else
arg = ((Scheme_App3_Rec *)a)->rand2;
}
if (SAME_TYPE(SCHEME_TYPE(arg), scheme_application3_type)) {
Scheme_App3_Rec *a3 = (Scheme_App3_Rec *)arg;
if (!SAME_OBJ(a3->rator, scheme_cons_proc))
return 0;
if (SAME_TYPE(SCHEME_TYPE(a3->rand1), scheme_struct_property_type)
/* `prop:chaperone-unsafe-undefined` affects the constructor */
&& !SAME_OBJ(a3->rand1, scheme_chaperone_undefined_property)) {
if (!scheme_omittable_expr(a3->rand2, 1, 3, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))
return 0;
} else
return 0;
} else
return 0;
}
return 1;
}
Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved,
int must_always_succeed, int check_auto,
GC_CAN_IGNORE int *_auto_e_depth,
@ -1248,10 +1201,9 @@ Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int
/* Checks whether it's a `make-struct-type' call --- that, if `must_always_succeed` is
true, certainly succeeds (i.e., no exception) --- pending a check of the auto-value
argument if !check_auto. The resulting constructor must always succeed (i.e., no
guards) and not involve chaperones (i.e., no `prop:chaperone-unsafe-undefined`).
The result is the auto-value argument or scheme_true if it's simple, NULL if not.
The first result is a struct type, the second a constructor, and the thrd a predicate;
the rest are an unspecified mixture of selectors and mutators. */
guards). The result is the auto-value argument or scheme_true if it's simple, NULL if not.
The first result of `e` will be a struct type, the second a constructor, and the third a predicate;
the rest are selectors and mutators. */
{
if (!fuel) return NULL;
@ -1285,9 +1237,13 @@ Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int
&& ((app->num_args < 6)
/* no properties... */
|| SCHEME_NULLP(app->args[6])
/* ... or properties that don't affect the constructor ... */
/* ... or properties that might make the `make-struct-type`
call itself fail, but otherwise don't affect the constructor
or selectors in a way that matters (although supplying the
`prop:chaperone-unsafe-undefined` property can affect the
constructor in an optimizer-irrelevant way) */
|| (!must_always_succeed
&& is_simple_property_list(app->args[6], resolved)))
&& scheme_omittable_expr(app->args[6], 1, 4, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL)))
&& ((app->num_args < 7)
/* inspector: */
|| SCHEME_FALSEP(app->args[7])