optimize: repair some make-struct-type[-property]
handling
Don't discard expressions that will fail due to trying to make a prefab struct type from a parent that isn't a prefab. Similarly, don't discard a `make-struct-type` with a built-in property that has a guard. Don't discard a `make-struct-type-property` with a literal guard procedure that has the wrong arity. Related to #2685
This commit is contained in:
parent
07e35566e2
commit
2f47629f74
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
(define collection 'multi)
|
(define collection 'multi)
|
||||||
|
|
||||||
(define version "7.3.0.5")
|
(define version "7.3.0.6")
|
||||||
|
|
||||||
(define deps `("racket-lib"
|
(define deps `("racket-lib"
|
||||||
["racket" #:version ,version]))
|
["racket" #:version ,version]))
|
||||||
|
|
|
@ -3714,7 +3714,18 @@
|
||||||
(make-struct-type-property 'a)
|
(make-struct-type-property 'a)
|
||||||
10)
|
10)
|
||||||
'(lambda ()
|
'(lambda ()
|
||||||
10))
|
10))
|
||||||
|
|
||||||
|
(test-comp '(lambda ()
|
||||||
|
(make-struct-type-property 'a (lambda () 'was-wrong-arity))
|
||||||
|
5)
|
||||||
|
'(lambda () 5)
|
||||||
|
#f)
|
||||||
|
(test-comp '(lambda ()
|
||||||
|
(make-struct-type-property 'a (lambda (x) 'was-wrong-arity))
|
||||||
|
5)
|
||||||
|
'(lambda () 5)
|
||||||
|
#f)
|
||||||
|
|
||||||
(test-comp '(module m racket/base
|
(test-comp '(module m racket/base
|
||||||
(define-values (prop:a a? a-ref) (make-struct-type-property 'a))
|
(define-values (prop:a a? a-ref) (make-struct-type-property 'a))
|
||||||
|
@ -3777,6 +3788,13 @@
|
||||||
(define (g y) (list y)))
|
(define (g y) (list y)))
|
||||||
#f)
|
#f)
|
||||||
|
|
||||||
|
(test-comp '(lambda ()
|
||||||
|
;; The built-in `prop:object-name` property has a guard:
|
||||||
|
(make-struct-type 'bad #f 2 0 #f (list (cons prop:object-name 'bad-spec)))
|
||||||
|
5)
|
||||||
|
'(lambda () 5)
|
||||||
|
#f)
|
||||||
|
|
||||||
(module struct-type-property-a racket/base
|
(module struct-type-property-a racket/base
|
||||||
(provide prop:a)
|
(provide prop:a)
|
||||||
(define-values (prop:a a? a-ref) (make-struct-type-property 'a)))
|
(define-values (prop:a a? a-ref) (make-struct-type-property 'a)))
|
||||||
|
@ -3808,6 +3826,26 @@
|
||||||
(define (g y) (list y)))
|
(define (g y) (list y)))
|
||||||
#f)
|
#f)
|
||||||
|
|
||||||
|
(test-comp '(module m racket/base
|
||||||
|
(struct posn (x y) #:prefab)
|
||||||
|
(let ()
|
||||||
|
;; Should be able to tell that `struct:posn` is prefab
|
||||||
|
(make-struct-type 'also-posn struct:posn 2 0 #f null 'prefab)
|
||||||
|
(void))
|
||||||
|
(posn 1 2))
|
||||||
|
'(module m racket/base
|
||||||
|
(struct posn (x y) #:prefab)
|
||||||
|
(let ()
|
||||||
|
(void))
|
||||||
|
(posn 1 2)))
|
||||||
|
|
||||||
|
(test-comp '(lambda ()
|
||||||
|
;; `struct:date` is not prefab
|
||||||
|
(make-struct-type 'bad struct:date 2 0 #f null 'prefab)
|
||||||
|
5)
|
||||||
|
'(lambda () 5)
|
||||||
|
#f)
|
||||||
|
|
||||||
;; A function with a required optional argument creates a pattern like
|
;; A function with a required optional argument creates a pattern like
|
||||||
;; the ones above, but intermediate points include extra references
|
;; the ones above, but intermediate points include extra references
|
||||||
;; that make it difficult to check with `test-comp`
|
;; that make it difficult to check with `test-comp`
|
||||||
|
|
|
@ -1403,6 +1403,7 @@ static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
|
||||||
{
|
{
|
||||||
Scheme_Object **_parent_identity = (Scheme_Object **)((void **)data)[0];
|
Scheme_Object **_parent_identity = (Scheme_Object **)((void **)data)[0];
|
||||||
int *_nonfail_constr = (int *)((void **)data)[1];
|
int *_nonfail_constr = (int *)((void **)data)[1];
|
||||||
|
int *_prefab = (int *)((void **)data)[2];
|
||||||
|
|
||||||
if (mode == OK_CONSTANT_SHAPE) {
|
if (mode == OK_CONSTANT_SHAPE) {
|
||||||
if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_proc_shape_type)) {
|
if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_proc_shape_type)) {
|
||||||
|
@ -1413,6 +1414,8 @@ static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
|
||||||
*_parent_identity = SCHEME_PROC_SHAPE_IDENTITY(v);
|
*_parent_identity = SCHEME_PROC_SHAPE_IDENTITY(v);
|
||||||
if (_nonfail_constr)
|
if (_nonfail_constr)
|
||||||
*_nonfail_constr = SCHEME_PROC_SHAPE_MODE(v) & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
*_nonfail_constr = SCHEME_PROC_SHAPE_MODE(v) & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
||||||
|
if (_prefab)
|
||||||
|
*_prefab = SCHEME_PROC_SHAPE_MODE(v) & STRUCT_PROC_SHAPE_PREFAB;
|
||||||
return field_count + 1;
|
return field_count + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1425,8 @@ static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
|
||||||
if ((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_STRUCT) {
|
if ((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_STRUCT) {
|
||||||
if (_nonfail_constr)
|
if (_nonfail_constr)
|
||||||
*_nonfail_constr = k & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
*_nonfail_constr = k & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
||||||
|
if (_prefab)
|
||||||
|
*_prefab = k & STRUCT_PROC_SHAPE_PREFAB;
|
||||||
return (k >> STRUCT_PROC_SHAPE_SHIFT) + 1;
|
return (k >> STRUCT_PROC_SHAPE_SHIFT) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1431,6 +1436,8 @@ static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
|
||||||
&& (k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_STRUCT) {
|
&& (k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_STRUCT) {
|
||||||
if (_nonfail_constr)
|
if (_nonfail_constr)
|
||||||
*_nonfail_constr = k & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
*_nonfail_constr = k & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
||||||
|
if (_prefab)
|
||||||
|
*_prefab = k & STRUCT_PROC_SHAPE_PREFAB;
|
||||||
return (k >> STRUCT_PROC_SHAPE_SHIFT) + 1;
|
return (k >> STRUCT_PROC_SHAPE_SHIFT) + 1;
|
||||||
}
|
}
|
||||||
} else if (mode == OK_CONSTANT_VARIANT) {
|
} else if (mode == OK_CONSTANT_VARIANT) {
|
||||||
|
@ -1444,6 +1451,8 @@ static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
|
||||||
if (mode == STRUCT_PROC_SHAPE_STRUCT) {
|
if (mode == STRUCT_PROC_SHAPE_STRUCT) {
|
||||||
if (_nonfail_constr)
|
if (_nonfail_constr)
|
||||||
*_nonfail_constr = SCHEME_INT_VAL(v) & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
*_nonfail_constr = SCHEME_INT_VAL(v) & STRUCT_PROC_SHAPE_NONFAIL_CONSTR;
|
||||||
|
if (_prefab)
|
||||||
|
*_prefab = SCHEME_INT_VAL(v) & STRUCT_PROC_SHAPE_PREFAB;
|
||||||
return field_count + 1;
|
return field_count + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1454,6 +1463,8 @@ static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
|
||||||
if (st->num_slots == st->num_islots) {
|
if (st->num_slots == st->num_islots) {
|
||||||
if (_nonfail_constr)
|
if (_nonfail_constr)
|
||||||
*_nonfail_constr = st->nonfail_constructor;
|
*_nonfail_constr = st->nonfail_constructor;
|
||||||
|
if (_prefab)
|
||||||
|
*_prefab = !!st->prefab_key;
|
||||||
return st->num_slots + 1;
|
return st->num_slots + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1468,13 +1479,15 @@ static int is_constant_super(Scheme_Object *arg,
|
||||||
Scheme_Object **runstack, int rs_delta,
|
Scheme_Object **runstack, int rs_delta,
|
||||||
Scheme_Linklet *enclosing_linklet,
|
Scheme_Linklet *enclosing_linklet,
|
||||||
Scheme_Object **_parent_identity,
|
Scheme_Object **_parent_identity,
|
||||||
int *_nonfail_constr)
|
int *_nonfail_constr,
|
||||||
|
int *_prefab)
|
||||||
/* Does `arg` produce another structure type (which can serve as a supertype)? */
|
/* Does `arg` produce another structure type (which can serve as a supertype)? */
|
||||||
{
|
{
|
||||||
void *data[2];
|
void *data[3];
|
||||||
|
|
||||||
data[0] = _parent_identity;
|
data[0] = _parent_identity;
|
||||||
data[1] = _nonfail_constr;
|
data[1] = _nonfail_constr;
|
||||||
|
data[2] = _prefab;
|
||||||
|
|
||||||
return is_ok_value(ok_constant_super_value, data,
|
return is_ok_value(ok_constant_super_value, data,
|
||||||
arg,
|
arg,
|
||||||
|
@ -1486,7 +1499,7 @@ static int is_constant_super(Scheme_Object *arg,
|
||||||
|
|
||||||
static int ok_constant_property_without_guard(void *data, Scheme_Object *v, int mode)
|
static int ok_constant_property_without_guard(void *data, Scheme_Object *v, int mode)
|
||||||
{
|
{
|
||||||
intptr_t k = 0;
|
intptr_t k = -1;
|
||||||
|
|
||||||
if (mode == OK_CONSTANT_SHAPE) {
|
if (mode == OK_CONSTANT_SHAPE) {
|
||||||
if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_prop_proc_shape_type)) {
|
if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_prop_proc_shape_type)) {
|
||||||
|
@ -1629,7 +1642,7 @@ Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int
|
||||||
|
|
||||||
if ((app->num_args >= 4) && (app->num_args <= 11)
|
if ((app->num_args >= 4) && (app->num_args <= 11)
|
||||||
&& SAME_OBJ(scheme_make_struct_type_proc, app->args[0])) {
|
&& SAME_OBJ(scheme_make_struct_type_proc, app->args[0])) {
|
||||||
int super_count_plus_one, super_nonfail_constr = 1;
|
int super_count_plus_one, super_nonfail_constr = 1, super_prefab = 1;
|
||||||
|
|
||||||
if (_parent_identity)
|
if (_parent_identity)
|
||||||
*_parent_identity = scheme_null;
|
*_parent_identity = scheme_null;
|
||||||
|
@ -1638,7 +1651,8 @@ Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int
|
||||||
info, top_level_table, runstack,
|
info, top_level_table, runstack,
|
||||||
rs_delta + app->num_args,
|
rs_delta + app->num_args,
|
||||||
enclosing_linklet, _parent_identity,
|
enclosing_linklet, _parent_identity,
|
||||||
&super_nonfail_constr);
|
&super_nonfail_constr,
|
||||||
|
&super_prefab);
|
||||||
else
|
else
|
||||||
super_count_plus_one = 0;
|
super_count_plus_one = 0;
|
||||||
|
|
||||||
|
@ -1673,7 +1687,8 @@ Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int
|
||||||
&& ((app->num_args < 7)
|
&& ((app->num_args < 7)
|
||||||
/* inspector: */
|
/* inspector: */
|
||||||
|| SCHEME_FALSEP(app->args[7])
|
|| SCHEME_FALSEP(app->args[7])
|
||||||
|| (SCHEME_SYMBOLP(app->args[7])
|
|| (super_prefab
|
||||||
|
&& SCHEME_SYMBOLP(app->args[7])
|
||||||
&& !strcmp("prefab", SCHEME_SYM_VAL(app->args[7]))
|
&& !strcmp("prefab", SCHEME_SYM_VAL(app->args[7]))
|
||||||
&& !SCHEME_SYM_WEIRDP(app->args[7]))
|
&& !SCHEME_SYM_WEIRDP(app->args[7]))
|
||||||
|| is_inspector_call(app->args[7]))
|
|| is_inspector_call(app->args[7]))
|
||||||
|
@ -1722,6 +1737,8 @@ Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int
|
||||||
_stinfo->authentic = authentic;
|
_stinfo->authentic = authentic;
|
||||||
_stinfo->nonfail_constructor = (super_nonfail_constr
|
_stinfo->nonfail_constructor = (super_nonfail_constr
|
||||||
&& ((app->num_args < 10) || SCHEME_FALSEP(app->args[10])));
|
&& ((app->num_args < 10) || SCHEME_FALSEP(app->args[10])));
|
||||||
|
_stinfo->prefab = ((app->num_args > 7)
|
||||||
|
&& SCHEME_SYMBOLP(app->args[7]));
|
||||||
_stinfo->num_gets = 1;
|
_stinfo->num_gets = 1;
|
||||||
_stinfo->num_sets = 1;
|
_stinfo->num_sets = 1;
|
||||||
}
|
}
|
||||||
|
@ -1807,7 +1824,8 @@ int scheme_is_simple_make_struct_type_property(Scheme_Object *e, int vals, int f
|
||||||
Scheme_Linklet *enclosing_linklet,
|
Scheme_Linklet *enclosing_linklet,
|
||||||
int fuel)
|
int fuel)
|
||||||
/* Reports whether `app` is a call to `make-struct-type-property` to
|
/* Reports whether `app` is a call to `make-struct-type-property` to
|
||||||
produce a propert with no guard. */
|
produce a property. The `flag` argument can indicate further that the
|
||||||
|
expression must always succeed without raising an exception. */
|
||||||
{
|
{
|
||||||
int resolved = (flags & CHECK_STRUCT_TYPE_RESOLVED);
|
int resolved = (flags & CHECK_STRUCT_TYPE_RESOLVED);
|
||||||
|
|
||||||
|
@ -1828,7 +1846,9 @@ int scheme_is_simple_make_struct_type_property(Scheme_Object *e, int vals, int f
|
||||||
if (SAME_OBJ(app->rator, scheme_make_struct_type_property_proc)) {
|
if (SAME_OBJ(app->rator, scheme_make_struct_type_property_proc)) {
|
||||||
if (SCHEME_SYMBOLP(app->rand1)
|
if (SCHEME_SYMBOLP(app->rand1)
|
||||||
&& (!(flags & CHECK_STRUCT_TYPE_ALWAYS_SUCCEED)
|
&& (!(flags & CHECK_STRUCT_TYPE_ALWAYS_SUCCEED)
|
||||||
|| SCHEME_LAMBDAP(app->rand2))
|
|| SCHEME_FALSEP(app->rand2)
|
||||||
|
|| (SCHEME_LAMBDAP(app->rand2)
|
||||||
|
&& (((Scheme_Lambda *)app->rand2)->num_params == 2)))
|
||||||
&& (scheme_omittable_expr(app->rator, 1, 4, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))) {
|
&& (scheme_omittable_expr(app->rator, 1, 4, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))) {
|
||||||
if (_has_guard) *_has_guard = 1;
|
if (_has_guard) *_has_guard = 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1851,6 +1871,7 @@ intptr_t scheme_get_struct_proc_shape(int k, Simple_Struct_Type_Info *stinfo)
|
||||||
return (STRUCT_PROC_SHAPE_STRUCT
|
return (STRUCT_PROC_SHAPE_STRUCT
|
||||||
| (stinfo->authentic ? STRUCT_PROC_SHAPE_AUTHENTIC : 0)
|
| (stinfo->authentic ? STRUCT_PROC_SHAPE_AUTHENTIC : 0)
|
||||||
| (stinfo->nonfail_constructor ? STRUCT_PROC_SHAPE_NONFAIL_CONSTR : 0)
|
| (stinfo->nonfail_constructor ? STRUCT_PROC_SHAPE_NONFAIL_CONSTR : 0)
|
||||||
|
| (stinfo->prefab ? STRUCT_PROC_SHAPE_PREFAB : 0)
|
||||||
| (stinfo->field_count << STRUCT_PROC_SHAPE_SHIFT));
|
| (stinfo->field_count << STRUCT_PROC_SHAPE_SHIFT));
|
||||||
else
|
else
|
||||||
return STRUCT_PROC_SHAPE_OTHER;
|
return STRUCT_PROC_SHAPE_OTHER;
|
||||||
|
|
|
@ -3073,6 +3073,7 @@ typedef struct {
|
||||||
int indexed_ops; /* do selectors have the index built in (as opposed to taking an index argument)? */
|
int indexed_ops; /* do selectors have the index built in (as opposed to taking an index argument)? */
|
||||||
int authentic; /* conservatively 0 is ok */
|
int authentic; /* conservatively 0 is ok */
|
||||||
int nonfail_constructor;
|
int nonfail_constructor;
|
||||||
|
int prefab;
|
||||||
int num_gets, num_sets;
|
int num_gets, num_sets;
|
||||||
int setter_fields; /* if indexed, bitmap for first 32 fields to indicate which have setters */
|
int setter_fields; /* if indexed, bitmap for first 32 fields to indicate which have setters */
|
||||||
} Simple_Struct_Type_Info;
|
} Simple_Struct_Type_Info;
|
||||||
|
@ -3110,7 +3111,8 @@ Scheme_Object *scheme_make_struct_proc_shape(intptr_t k, Scheme_Object *identity
|
||||||
#define STRUCT_PROC_SHAPE_MASK 0xF
|
#define STRUCT_PROC_SHAPE_MASK 0xF
|
||||||
#define STRUCT_PROC_SHAPE_AUTHENTIC 0x10
|
#define STRUCT_PROC_SHAPE_AUTHENTIC 0x10
|
||||||
#define STRUCT_PROC_SHAPE_NONFAIL_CONSTR 0x20
|
#define STRUCT_PROC_SHAPE_NONFAIL_CONSTR 0x20
|
||||||
#define STRUCT_PROC_SHAPE_SHIFT 6
|
#define STRUCT_PROC_SHAPE_PREFAB 0x40
|
||||||
|
#define STRUCT_PROC_SHAPE_SHIFT 7
|
||||||
|
|
||||||
typedef struct Scheme_Struct_Proc_Shape {
|
typedef struct Scheme_Struct_Proc_Shape {
|
||||||
Scheme_Object so;
|
Scheme_Object so;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#define MZSCHEME_VERSION_X 7
|
#define MZSCHEME_VERSION_X 7
|
||||||
#define MZSCHEME_VERSION_Y 3
|
#define MZSCHEME_VERSION_Y 3
|
||||||
#define MZSCHEME_VERSION_Z 0
|
#define MZSCHEME_VERSION_Z 0
|
||||||
#define MZSCHEME_VERSION_W 5
|
#define MZSCHEME_VERSION_W 6
|
||||||
|
|
||||||
/* A level of indirection makes `#` work as needed: */
|
/* A level of indirection makes `#` work as needed: */
|
||||||
#define AS_a_STR_HELPER(x) #x
|
#define AS_a_STR_HELPER(x) #x
|
||||||
|
|
|
@ -3423,6 +3423,10 @@ intptr_t scheme_get_or_check_structure_shape(Scheme_Object *e, Scheme_Object *ex
|
||||||
| ((st->nonfail_constructor
|
| ((st->nonfail_constructor
|
||||||
&& (!expected || (v & STRUCT_PROC_SHAPE_NONFAIL_CONSTR)))
|
&& (!expected || (v & STRUCT_PROC_SHAPE_NONFAIL_CONSTR)))
|
||||||
? STRUCT_PROC_SHAPE_NONFAIL_CONSTR
|
? STRUCT_PROC_SHAPE_NONFAIL_CONSTR
|
||||||
|
: 0)
|
||||||
|
| ((st->prefab_key
|
||||||
|
&& (!expected || (v & STRUCT_PROC_SHAPE_PREFAB)))
|
||||||
|
? STRUCT_PROC_SHAPE_PREFAB
|
||||||
: 0));
|
: 0));
|
||||||
} else if (!SCHEME_PRIMP(e)) {
|
} else if (!SCHEME_PRIMP(e)) {
|
||||||
want_v = -1;
|
want_v = -1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user