track information about `struct' bindings during compilation
This tracking allows the compiler to treat structure sub-type declarations as generating constant results, and it also allows the compiler to recognize an applications of a constructor or predicate as functional.
This commit is contained in:
parent
e698be778b
commit
5f30cc87ea
|
@ -516,7 +516,10 @@
|
|||
stx
|
||||
super-id))
|
||||
(and super-expr
|
||||
#`(check-struct-type 'fm #,super-expr)))]
|
||||
#`(let ([the-super #,super-expr])
|
||||
(if (struct-type? the-super)
|
||||
the-super
|
||||
(check-struct-type 'fm the-super)))))]
|
||||
[prune (lambda (stx) (identifier-prune-lexical-context stx
|
||||
(list (syntax-e stx) '#%top)))]
|
||||
[reflect-name-expr (if reflect-name-expr
|
||||
|
|
|
@ -1682,6 +1682,154 @@
|
|||
(hash-ref '#hash((x . y)) x add1))
|
||||
#f)
|
||||
|
||||
;; Check elimination of ignored structure predicate
|
||||
;; and constructor applications:
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(define-values (struct:a a a? a-ref a-set!)
|
||||
(make-struct-type 'a #f 2 0))
|
||||
(begin0
|
||||
(a? (a-ref (a 1 2) 1))
|
||||
a?
|
||||
a
|
||||
a-ref
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(define-values (struct:a a a? a-ref a-set!)
|
||||
(make-struct-type 'a #f 2 0))
|
||||
(begin0
|
||||
(a? (a-ref (a 1 2) 1))
|
||||
5)))
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(define-values (struct:a a a? a-x a-y)
|
||||
(let-values ([(struct:a a a? a-ref a-set!)
|
||||
(make-struct-type 'a #f 2 0)])
|
||||
(values struct:a a a?
|
||||
(make-struct-field-accessor a-ref 0)
|
||||
(make-struct-field-accessor a-ref 1))))
|
||||
(begin0
|
||||
(a? (a-x (a 1 2)))
|
||||
a?
|
||||
a
|
||||
a-x
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(define-values (struct:a a a? a-x a-y)
|
||||
(let-values ([(struct:a a a? a-ref a-set!)
|
||||
(make-struct-type 'a #f 2 0)])
|
||||
(values struct:a a a?
|
||||
(make-struct-field-accessor a-ref 0)
|
||||
(make-struct-field-accessor a-ref 1))))
|
||||
(begin0
|
||||
(a? (a-x (a 1 2)))
|
||||
5)))
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes)
|
||||
(begin0
|
||||
(a? (a-x (a 1 2)))
|
||||
a?
|
||||
a
|
||||
a-x
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes)
|
||||
(begin0
|
||||
(a? (a-x (a 1 2)))
|
||||
5)))
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes #:prefab)
|
||||
(begin0
|
||||
(a? (a-x (a 1 2)))
|
||||
a?
|
||||
a
|
||||
a-x
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes #:prefab)
|
||||
(begin0
|
||||
(a? (a-x (a 1 2)))
|
||||
5)))
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes #:mutable)
|
||||
(begin0
|
||||
(a? (set-a-x! (a 1 2) 5))
|
||||
a?
|
||||
a
|
||||
a-x
|
||||
set-a-x!
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes #:mutable)
|
||||
(begin0
|
||||
(a? (set-a-x! (a 1 2) 5))
|
||||
5)))
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes)
|
||||
(struct b (z) #:super struct:a #:omit-define-syntaxes)
|
||||
(begin0
|
||||
(list (a? (a-x (a 1 2)))
|
||||
(b? (b-z (b 1 2 3))))
|
||||
a?
|
||||
a
|
||||
a-x
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
b?
|
||||
b
|
||||
b-z
|
||||
(b 1 2 3)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(struct a (x y) #:omit-define-syntaxes)
|
||||
(struct b (z) #:super struct:a #:omit-define-syntaxes)
|
||||
(begin0
|
||||
(list (a? (a-x (a 1 2)))
|
||||
(b? (b-z (b 1 2 3))))
|
||||
5)))
|
||||
|
||||
(module struct-a-for-optimize racket/base
|
||||
(provide (struct-out a)
|
||||
(struct-out b))
|
||||
(struct a (x y))
|
||||
(struct b a (z)))
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(require 'struct-a-for-optimize)
|
||||
(begin0
|
||||
(list (a? (a-x (a 1 2)))
|
||||
(b? (b-z (b 1 2 3))))
|
||||
a?
|
||||
a
|
||||
a-x
|
||||
(a? 7)
|
||||
(a 1 2)
|
||||
b?
|
||||
b
|
||||
b-z
|
||||
(b 1 2 3)
|
||||
5))
|
||||
'(module m racket/base
|
||||
(require 'struct-a-for-optimize)
|
||||
(begin0
|
||||
(list (a? (a-x (a 1 2)))
|
||||
(b? (b-z (b 1 2 3))))
|
||||
5)))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Check bytecode verification of lifted functions
|
||||
|
||||
|
|
|
@ -2000,7 +2000,11 @@ scheme_lookup_binding(Scheme_Object *find_id, Scheme_Comp_Env *env, int flags,
|
|||
is_constant = 2;
|
||||
else if (SAME_OBJ(mod_constant, scheme_fixed_key))
|
||||
is_constant = 1;
|
||||
else if (SAME_TYPE(SCHEME_TYPE(mod_constant), scheme_inline_variant_type)) {
|
||||
else if (SAME_TYPE(SCHEME_TYPE(mod_constant), scheme_struct_proc_shape_type)) {
|
||||
if (_inline_variant)
|
||||
*_inline_variant = mod_constant;
|
||||
is_constant = 2;
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(mod_constant), scheme_inline_variant_type)) {
|
||||
if (_inline_variant)
|
||||
*_inline_variant = mod_constant;
|
||||
is_constant = 2;
|
||||
|
|
|
@ -2923,7 +2923,7 @@ Scheme_Object *scheme_make_sequence_compilation(Scheme_Object *seq, int opt)
|
|||
total++;
|
||||
} else if (opt
|
||||
&& (((opt > 0) && !last) || ((opt < 0) && !first))
|
||||
&& scheme_omittable_expr(v, -1, -1, 0, NULL, -1, 0)) {
|
||||
&& scheme_omittable_expr(v, -1, -1, 0, NULL, NULL, -1, 0)) {
|
||||
/* A value that is not the result. We'll drop it. */
|
||||
total++;
|
||||
} else {
|
||||
|
@ -2951,7 +2951,7 @@ Scheme_Object *scheme_make_sequence_compilation(Scheme_Object *seq, int opt)
|
|||
/* can't optimize away a begin0 at read time; it's too late, since the
|
||||
return is combined with EXPD_BEGIN0 */
|
||||
addconst = 1;
|
||||
} else if ((opt < 0) && !scheme_omittable_expr(SCHEME_CAR(seq), 1, -1, 0, NULL, -1, 0)) {
|
||||
} else if ((opt < 0) && !scheme_omittable_expr(SCHEME_CAR(seq), 1, -1, 0, NULL, NULL, -1, 0)) {
|
||||
/* We can't optimize (begin0 expr cont) to expr because
|
||||
exp is not in tail position in the original (so we'd mess
|
||||
up continuation marks). */
|
||||
|
@ -2983,7 +2983,7 @@ Scheme_Object *scheme_make_sequence_compilation(Scheme_Object *seq, int opt)
|
|||
} else if (opt
|
||||
&& (((opt > 0) && (k < total))
|
||||
|| ((opt < 0) && k))
|
||||
&& scheme_omittable_expr(v, -1, -1, 0, NULL, -1, 0)) {
|
||||
&& scheme_omittable_expr(v, -1, -1, 0, NULL, NULL, -1, 0)) {
|
||||
/* Value not the result. Do nothing. */
|
||||
} else
|
||||
o->array[i++] = v;
|
||||
|
@ -3483,7 +3483,7 @@ static Scheme_Object *eval_letmacro_rhs(Scheme_Object *a, Scheme_Comp_Env *rhs_e
|
|||
|
||||
save_runstack = scheme_push_prefix(NULL, rp, NULL, NULL, phase, phase, rhs_env->genv, NULL);
|
||||
|
||||
if (scheme_omittable_expr(a, 1, -1, 0, NULL, -1, 0)) {
|
||||
if (scheme_omittable_expr(a, 1, -1, 0, NULL, NULL, -1, 0)) {
|
||||
/* short cut */
|
||||
a = _scheme_eval_linked_expr_multi(a);
|
||||
} else {
|
||||
|
|
|
@ -1896,7 +1896,13 @@ define_execute_with_dynamic_state(Scheme_Object *vec, int delta, int defmacro,
|
|||
if (SAME_OBJ(values, scheme_current_thread->values_buffer))
|
||||
scheme_current_thread->values_buffer = NULL;
|
||||
|
||||
is_st = scheme_is_simple_make_struct_type(vals_expr, g, 1, 1);
|
||||
if (dm_env)
|
||||
is_st = 0;
|
||||
else
|
||||
is_st = !!scheme_is_simple_make_struct_type(vals_expr, g, 1, 1,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, MZ_RUNSTACK, 0,
|
||||
NULL, NULL, 5);
|
||||
|
||||
for (i = 0; i < g; i++) {
|
||||
var = SCHEME_VEC_ELS(vec)[i+delta];
|
||||
|
|
|
@ -1520,9 +1520,14 @@ int scheme_generate_struct_op(mz_jit_state *jitter, int kind, int for_branch,
|
|||
}
|
||||
} else {
|
||||
if (type_pos != 0) {
|
||||
(void)jit_blti_i(refslow2, JIT_R2, type_pos);
|
||||
}
|
||||
bref3 = NULL;
|
||||
if (kind == 1) {
|
||||
bref3 = jit_blti_i(jit_forward(), JIT_R2, type_pos);
|
||||
} else {
|
||||
(void)jit_blti_i(refslow2, JIT_R2, type_pos);
|
||||
bref3 = NULL;
|
||||
}
|
||||
} else
|
||||
bref3 = NULL;
|
||||
}
|
||||
CHECK_LIMIT();
|
||||
/* Lookup argument type at target type depth, put it in R2: */
|
||||
|
|
|
@ -4121,7 +4121,7 @@ static void setup_accessible_table(Scheme_Module *m)
|
|||
for (i = 0; i < cnt; i++) {
|
||||
form = SCHEME_VEC_ELS(m->bodies[0])[i];
|
||||
if (SAME_TYPE(SCHEME_TYPE(form), scheme_define_values_type)) {
|
||||
int checked_st = 0, is_st = 0;
|
||||
int checked_st = 0, is_st = 0, st_count = 0, st_icount = 0;
|
||||
for (k = SCHEME_VEC_SIZE(form); k-- > 1; ) {
|
||||
tl = SCHEME_VEC_ELS(form)[k];
|
||||
if (SCHEME_TOPLEVEL_FLAGS(tl) & SCHEME_TOPLEVEL_SEAL) {
|
||||
|
@ -4154,13 +4154,17 @@ static void setup_accessible_table(Scheme_Module *m)
|
|||
}
|
||||
} else {
|
||||
if (!checked_st) {
|
||||
is_st = scheme_is_simple_make_struct_type(SCHEME_VEC_ELS(form)[0],
|
||||
SCHEME_VEC_SIZE(form)-1,
|
||||
1, 1);
|
||||
is_st = !!scheme_is_simple_make_struct_type(SCHEME_VEC_ELS(form)[0],
|
||||
SCHEME_VEC_SIZE(form)-1,
|
||||
1, 1, NULL, &st_count, &st_icount,
|
||||
NULL,
|
||||
NULL, NULL, NULL, 0,
|
||||
m->prefix->toplevels, ht,
|
||||
5);
|
||||
checked_st = 1;
|
||||
}
|
||||
if (is_st)
|
||||
v = scheme_make_pair(v, scheme_constant_key);
|
||||
v = scheme_make_pair(v, scheme_make_struct_proc_shape(k-1, st_count, st_icount));
|
||||
}
|
||||
scheme_hash_set(ht, tl, v);
|
||||
}
|
||||
|
@ -9002,7 +9006,7 @@ static Scheme_Object *do_module_begin_at_phase(Scheme_Object *form, Scheme_Comp_
|
|||
Scheme_Object *prev = NULL, *next;
|
||||
for (p = first; !SCHEME_NULLP(p); p = next) {
|
||||
next = SCHEME_CDR(p);
|
||||
if (scheme_omittable_expr(SCHEME_CAR(p), -1, -1, 0, NULL, -1, 0)) {
|
||||
if (scheme_omittable_expr(SCHEME_CAR(p), -1, -1, 0, NULL, NULL, -1, 0)) {
|
||||
if (prev)
|
||||
SCHEME_CDR(prev) = next;
|
||||
else
|
||||
|
|
|
@ -248,6 +248,25 @@ static int small_object_FIXUP(void *p, struct NewGC *gc) {
|
|||
#define small_object_IS_CONST_SIZE 1
|
||||
|
||||
|
||||
static int small_atomic_obj_SIZE(void *p, struct NewGC *gc) {
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
static int small_atomic_obj_MARK(void *p, struct NewGC *gc) {
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
static int small_atomic_obj_FIXUP(void *p, struct NewGC *gc) {
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
#define small_atomic_obj_IS_ATOMIC 1
|
||||
#define small_atomic_obj_IS_CONST_SIZE 1
|
||||
|
||||
|
||||
static int app_rec_SIZE(void *p, struct NewGC *gc) {
|
||||
Scheme_App_Rec *r = (Scheme_App_Rec *)p;
|
||||
|
||||
|
@ -1191,25 +1210,6 @@ static int escaping_cont_proc_FIXUP(void *p, struct NewGC *gc) {
|
|||
#define escaping_cont_proc_IS_CONST_SIZE 1
|
||||
|
||||
|
||||
static int char_obj_SIZE(void *p, struct NewGC *gc) {
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
static int char_obj_MARK(void *p, struct NewGC *gc) {
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
static int char_obj_FIXUP(void *p, struct NewGC *gc) {
|
||||
return
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
#define char_obj_IS_ATOMIC 1
|
||||
#define char_obj_IS_CONST_SIZE 1
|
||||
|
||||
|
||||
static int bignum_obj_SIZE(void *p, struct NewGC *gc) {
|
||||
Scheme_Bignum *b = (Scheme_Bignum *)p;
|
||||
|
||||
|
|
|
@ -89,6 +89,12 @@ small_object {
|
|||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
small_atomic_obj {
|
||||
mark:
|
||||
size:
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
app_rec {
|
||||
Scheme_App_Rec *r = (Scheme_App_Rec *)p;
|
||||
|
||||
|
@ -467,12 +473,6 @@ escaping_cont_proc {
|
|||
gcBYTES_TO_WORDS(sizeof(Scheme_Escaping_Cont));
|
||||
}
|
||||
|
||||
char_obj {
|
||||
mark:
|
||||
size:
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Small_Object));
|
||||
}
|
||||
|
||||
bignum_obj {
|
||||
Scheme_Bignum *b = (Scheme_Bignum *)p;
|
||||
|
||||
|
|
|
@ -118,6 +118,8 @@ static Scheme_Object *optimize_shift(Scheme_Object *obj, int delta, int after_de
|
|||
|
||||
static int compiled_proc_body_size(Scheme_Object *o, int less_args);
|
||||
|
||||
READ_ONLY static Scheme_Object *struct_proc_shape_other;
|
||||
|
||||
typedef struct Scheme_Once_Used {
|
||||
Scheme_Object so;
|
||||
Scheme_Object *expr;
|
||||
|
@ -143,6 +145,9 @@ void scheme_init_optimize()
|
|||
#ifdef MZ_PRECISE_GC
|
||||
register_traversers();
|
||||
#endif
|
||||
|
||||
REGISTER_SO(struct_proc_shape_other);
|
||||
struct_proc_shape_other = scheme_make_struct_proc_shape(3, 0, 0);
|
||||
}
|
||||
|
||||
/*========================================================================*/
|
||||
|
@ -167,6 +172,47 @@ int scheme_is_functional_primitive(Scheme_Object *rator, int num_args, int expec
|
|||
return 0;
|
||||
}
|
||||
|
||||
static Scheme_Object *get_struct_proc_shape(Scheme_Object *rator, Optimize_Info *info)
|
||||
{
|
||||
Scheme_Object *c;
|
||||
|
||||
if (info
|
||||
&& (info->top_level_consts || info->cp->inline_variants)
|
||||
&& SAME_TYPE(SCHEME_TYPE(rator), scheme_compiled_toplevel_type)) {
|
||||
int pos;
|
||||
pos = SCHEME_TOPLEVEL_POS(rator);
|
||||
c = NULL;
|
||||
if (info->top_level_consts)
|
||||
c = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
|
||||
if (!c && info->cp->inline_variants)
|
||||
c = scheme_hash_get(info->cp->inline_variants, scheme_make_integer(pos));
|
||||
if (c && SAME_TYPE(SCHEME_TYPE(c), scheme_struct_proc_shape_type)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int scheme_is_struct_functional(Scheme_Object *rator, int num_args, Optimize_Info *info, int vals)
|
||||
{
|
||||
Scheme_Object *c;
|
||||
|
||||
if ((vals == 1) || (vals == -1)) {
|
||||
c = get_struct_proc_shape(rator, info);
|
||||
if (c) {
|
||||
int mode = (SCHEME_PROC_SHAPE_MODE(c) & STRUCT_PROC_SHAPE_MASK);
|
||||
int field_count = (SCHEME_PROC_SHAPE_MODE(c) >> STRUCT_PROC_SHAPE_SHIFT);
|
||||
if (((num_args == 1) && (mode == STRUCT_PROC_SHAPE_PRED))
|
||||
|| ((num_args == field_count) && (mode == STRUCT_PROC_SHAPE_CONSTR))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void note_match(int actual, int expected, Optimize_Info *warn_info)
|
||||
{
|
||||
if (!warn_info || (expected == -1))
|
||||
|
@ -183,7 +229,7 @@ static void note_match(int actual, int expected, Optimize_Info *warn_info)
|
|||
}
|
||||
|
||||
int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
||||
Optimize_Info *warn_info, int deeper_than, int no_id)
|
||||
Optimize_Info *opt_info, Optimize_Info *warn_info, int deeper_than, int no_id)
|
||||
/* Checks whether the bytecode `o' returns `vals' values with no
|
||||
side-effects and without pushing and using continuation marks.
|
||||
-1 for vals means that any return count is ok.
|
||||
|
@ -258,9 +304,9 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
if (vtype == scheme_branch_type) {
|
||||
Scheme_Branch_Rec *b;
|
||||
b = (Scheme_Branch_Rec *)o;
|
||||
return (scheme_omittable_expr(b->test, 1, fuel - 1, resolved, warn_info, deeper_than, 0)
|
||||
&& scheme_omittable_expr(b->tbranch, vals, fuel - 1, resolved, warn_info, deeper_than, no_id)
|
||||
&& scheme_omittable_expr(b->fbranch, vals, fuel - 1, resolved, warn_info, deeper_than, no_id));
|
||||
return (scheme_omittable_expr(b->test, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than, 0)
|
||||
&& scheme_omittable_expr(b->tbranch, vals, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id)
|
||||
&& scheme_omittable_expr(b->fbranch, vals, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -268,15 +314,15 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
a let_value_type! */
|
||||
if (vtype == scheme_let_value_type) {
|
||||
Scheme_Let_Value *lv = (Scheme_Let_Value *)o;
|
||||
return (scheme_omittable_expr(lv->value, lv->count, fuel - 1, resolved, warn_info, deeper_than, no_id)
|
||||
&& scheme_omittable_expr(lv->body, vals, fuel - 1, resolved, warn_info, deeper_than, no_id));
|
||||
return (scheme_omittable_expr(lv->value, lv->count, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id)
|
||||
&& scheme_omittable_expr(lv->body, vals, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vtype == scheme_let_one_type) {
|
||||
Scheme_Let_One *lo = (Scheme_Let_One *)o;
|
||||
return (scheme_omittable_expr(lo->value, 1, fuel - 1, resolved, warn_info, deeper_than + 1, 0)
|
||||
&& scheme_omittable_expr(lo->body, vals, fuel - 1, resolved, warn_info, deeper_than + 1, no_id));
|
||||
return (scheme_omittable_expr(lo->value, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than + 1, 0)
|
||||
&& scheme_omittable_expr(lo->body, vals, fuel - 1, resolved, opt_info, warn_info, deeper_than + 1, no_id));
|
||||
}
|
||||
|
||||
if (vtype == scheme_let_void_type) {
|
||||
|
@ -286,7 +332,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
Scheme_Let_Value *lv2 = (Scheme_Let_Value *)lv->body;
|
||||
if ((lv2->count == 1)
|
||||
&& (lv2->position == 0)
|
||||
&& scheme_omittable_expr(lv2->value, 1, fuel - 1, resolved, warn_info,
|
||||
&& scheme_omittable_expr(lv2->value, 1, fuel - 1, resolved, opt_info, warn_info,
|
||||
deeper_than + 1 + lv->count,
|
||||
0)) {
|
||||
o = lv2->body;
|
||||
|
@ -305,7 +351,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
if ((lh->count == 1) && (lh->num_clauses == 1)) {
|
||||
if (SAME_TYPE(SCHEME_TYPE(lh->body), scheme_compiled_let_value_type)) {
|
||||
Scheme_Compiled_Let_Value *lv = (Scheme_Compiled_Let_Value *)lh->body;
|
||||
if (scheme_omittable_expr(lv->value, 1, fuel - 1, resolved, warn_info, deeper_than + 1, 0)) {
|
||||
if (scheme_omittable_expr(lv->value, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than + 1, 0)) {
|
||||
o = lv->body;
|
||||
deeper_than++;
|
||||
goto try_again;
|
||||
|
@ -325,26 +371,19 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
if ((app->num_args >= 4) && (app->num_args <= 11)
|
||||
&& SAME_OBJ(scheme_make_struct_type_proc, app->args[0])) {
|
||||
note_match(5, vals, warn_info);
|
||||
if (scheme_is_simple_make_struct_type(o, vals, resolved, 0)) {
|
||||
if ((app->num_args < 5)
|
||||
/* auto-field value: */
|
||||
|| scheme_omittable_expr(app->args[5], 1, fuel - 1, resolved, warn_info,
|
||||
deeper_than + (resolved ? app->num_args : 0), 0)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SCHEME_PRIMP(app->args[0])) {
|
||||
if (scheme_is_functional_primitive(app->args[0], app->num_args, vals)) {
|
||||
int i;
|
||||
for (i = app->num_args; i--; ) {
|
||||
if (!scheme_omittable_expr(app->args[i + 1], 1, fuel - 1, resolved, warn_info,
|
||||
deeper_than + (resolved ? app->num_args : 0), 0))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} else if (!(SCHEME_PRIM_PROC_FLAGS(app->args[0]) & SCHEME_PRIM_IS_MULTI_RESULT)) {
|
||||
|
||||
if (scheme_is_functional_primitive(app->args[0], app->num_args, vals)
|
||||
|| scheme_is_struct_functional(app->args[0], app->num_args, opt_info, vals)) {
|
||||
int i;
|
||||
for (i = app->num_args; i--; ) {
|
||||
if (!scheme_omittable_expr(app->args[i + 1], 1, fuel - 1, resolved, opt_info, warn_info,
|
||||
deeper_than + (resolved ? app->num_args : 0), 0))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} else if (SCHEME_PRIMP(app->args[0])) {
|
||||
if (!(SCHEME_PRIM_PROC_FLAGS(app->args[0]) & SCHEME_PRIM_IS_MULTI_RESULT)) {
|
||||
note_match(1, vals, warn_info);
|
||||
} else if (SAME_OBJ(scheme_values_func, app->args[0])) {
|
||||
note_match(app->num_args, vals, warn_info);
|
||||
|
@ -356,13 +395,14 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
|
||||
if (vtype == scheme_application2_type) {
|
||||
Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
|
||||
if (SCHEME_PRIMP(app->rator)) {
|
||||
if (scheme_is_functional_primitive(app->rator, 1, vals)) {
|
||||
if (scheme_omittable_expr(app->rand, 1, fuel - 1, resolved, warn_info,
|
||||
deeper_than + (resolved ? 1 : 0), 0))
|
||||
return 1;
|
||||
} else if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)
|
||||
|| SAME_OBJ(scheme_values_func, app->rator)) {
|
||||
if (scheme_is_functional_primitive(app->rator, 1, vals)
|
||||
|| scheme_is_struct_functional(app->rator, 1, opt_info, vals)) {
|
||||
if (scheme_omittable_expr(app->rand, 1, fuel - 1, resolved, opt_info, warn_info,
|
||||
deeper_than + (resolved ? 1 : 0), 0))
|
||||
return 1;
|
||||
} else if (SCHEME_PRIMP(app->rator)) {
|
||||
if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)
|
||||
|| SAME_OBJ(scheme_values_func, app->rator)) {
|
||||
note_match(1, vals, warn_info);
|
||||
}
|
||||
}
|
||||
|
@ -371,14 +411,15 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
|
||||
if (vtype == scheme_application3_type) {
|
||||
Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
|
||||
if (SCHEME_PRIMP(app->rator)) {
|
||||
if (scheme_is_functional_primitive(app->rator, 2, vals)) {
|
||||
if (scheme_omittable_expr(app->rand1, 1, fuel - 1, resolved, warn_info,
|
||||
deeper_than + (resolved ? 2 : 0), 0)
|
||||
&& scheme_omittable_expr(app->rand2, 1, fuel - 1, resolved, warn_info,
|
||||
deeper_than + (resolved ? 2 : 0), 0))
|
||||
return 1;
|
||||
} else if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)) {
|
||||
if (scheme_is_functional_primitive(app->rator, 2, vals)
|
||||
|| scheme_is_struct_functional(app->rator, 2, opt_info, vals)) {
|
||||
if (scheme_omittable_expr(app->rand1, 1, fuel - 1, resolved, opt_info, warn_info,
|
||||
deeper_than + (resolved ? 2 : 0), 0)
|
||||
&& scheme_omittable_expr(app->rand2, 1, fuel - 1, resolved, opt_info, warn_info,
|
||||
deeper_than + (resolved ? 2 : 0), 0))
|
||||
return 1;
|
||||
} else if (SCHEME_PRIMP(app->rator)) {
|
||||
if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)) {
|
||||
note_match(1, vals, warn_info);
|
||||
} else if (SAME_OBJ(scheme_values_func, app->rator)) {
|
||||
note_match(2, vals, warn_info);
|
||||
|
@ -387,6 +428,22 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* check for struct-type declaration: */
|
||||
{
|
||||
Scheme_Object *auto_e;
|
||||
int auto_e_depth;
|
||||
auto_e = scheme_is_simple_make_struct_type(o, vals, resolved, 0, &auto_e_depth,
|
||||
NULL, NULL, NULL,
|
||||
(opt_info ? opt_info->top_level_consts : NULL),
|
||||
NULL, NULL, 0, NULL, NULL,
|
||||
5);
|
||||
if (auto_e) {
|
||||
if (scheme_omittable_expr(auto_e, 1, fuel - 1, resolved, opt_info, warn_info,
|
||||
deeper_than + auto_e_depth, 0))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -460,33 +517,58 @@ static int is_int_list(Scheme_Object *o, int up_to)
|
|||
return SCHEME_NULLP(o);
|
||||
}
|
||||
|
||||
static int is_values_with_accessors_and_mutators(Scheme_Object *e, int vals, int resolved)
|
||||
static int ok_proc_creator_args(Scheme_Object *rator, Scheme_Object *rand1, Scheme_Object *rand2, Scheme_Object *rand3,
|
||||
int delta2, int field_count)
|
||||
{
|
||||
if ((SAME_OBJ(rator, scheme_make_struct_field_accessor_proc)
|
||||
&& is_local_ref(rand1, delta2+3, 1))
|
||||
|| (SAME_OBJ(rator, scheme_make_struct_field_mutator_proc)
|
||||
&& is_local_ref(rand1, delta2+4, 1))) {
|
||||
if (SCHEME_INTP(rand2)
|
||||
&& (SCHEME_INT_VAL(rand2) >= 0)
|
||||
&& (SCHEME_INT_VAL(rand2) < field_count)
|
||||
&& (!rand3 || SCHEME_SYMBOLP(rand3))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_values_with_accessors_and_mutators(Scheme_Object *e, int vals, int resolved, int field_count)
|
||||
{
|
||||
if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)) {
|
||||
Scheme_App_Rec *app = (Scheme_App_Rec *)e;
|
||||
int delta = (resolved ? app->num_args : 0);
|
||||
if (SAME_OBJ(app->args[0], scheme_values_func)
|
||||
&& (app->num_args == vals)) {
|
||||
&& (app->num_args == vals)
|
||||
&& (app->num_args >= 3)
|
||||
&& is_local_ref(app->args[1], delta, 1)
|
||||
&& is_local_ref(app->args[2], delta+1, 1)
|
||||
&& is_local_ref(app->args[3], delta+2, 1)) {
|
||||
int i;
|
||||
for (i = app->num_args; i > 0; i--) {
|
||||
if (is_local_ref(app->args[1], delta, 5)) {
|
||||
for (i = app->num_args; i > 3; i--) {
|
||||
if (is_local_ref(app->args[i], delta, 5)) {
|
||||
/* ok */
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(app->args[i]), scheme_application3_type)) {
|
||||
Scheme_App3_Rec *app3 = (Scheme_App3_Rec *)app->args[i];
|
||||
int delta2 = delta + (resolved ? 2 : 0);
|
||||
if (SAME_OBJ(app3->rator, scheme_make_struct_field_accessor_proc)) {
|
||||
if (!is_local_ref(app3->rand1, delta2+3, 1)
|
||||
&& SCHEME_SYMBOLP(app3->rand2))
|
||||
break;
|
||||
} else if (SAME_OBJ(app3->rator, scheme_make_struct_field_mutator_proc)) {
|
||||
if (!is_local_ref(app3->rand1, delta2+4, 1)
|
||||
&& SCHEME_SYMBOLP(app3->rand2))
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(app->args[i]), scheme_application_type)) {
|
||||
Scheme_App_Rec *app3 = (Scheme_App_Rec *)app->args[i];
|
||||
int delta2 = delta + (resolved ? app3->num_args : 0);
|
||||
if (app3->num_args == 3) {
|
||||
if (!ok_proc_creator_args(app3->args[0], app3->args[1], app3->args[2], app3->args[3],
|
||||
delta2, field_count))
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(app->args[i]), scheme_application3_type)) {
|
||||
Scheme_App3_Rec *app3 = (Scheme_App3_Rec *)app->args[i];
|
||||
int delta2 = delta + (resolved ? 2 : 0);
|
||||
if (!ok_proc_creator_args(app3->rator, app3->rand1, app3->rand2, NULL,
|
||||
delta2, field_count))
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (i <= 0)
|
||||
if (i <= 3)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -509,18 +591,112 @@ static Scheme_Object *skip_clears(Scheme_Object *body)
|
|||
return body;
|
||||
}
|
||||
|
||||
int scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved, int check_auto)
|
||||
/* Checks whether it's a `make-struct-type' call that certainly succeeds
|
||||
(i.e., no exception) --- pending a check of argument 5 if !check_auto */
|
||||
static int is_constant_super(Scheme_Object *arg,
|
||||
Scheme_Hash_Table *top_level_consts,
|
||||
Scheme_Hash_Table *top_level_table,
|
||||
Scheme_Object **runstack, int rs_delta,
|
||||
Scheme_Object **symbols, Scheme_Hash_Table *symbol_table)
|
||||
{
|
||||
int pos;
|
||||
Scheme_Object *v;
|
||||
|
||||
if (SAME_TYPE(SCHEME_TYPE(arg), scheme_compiled_toplevel_type)) {
|
||||
pos = SCHEME_TOPLEVEL_POS(arg);
|
||||
if (top_level_consts) {
|
||||
/* This is optimize mode */
|
||||
v = scheme_hash_get(top_level_consts, scheme_make_integer(pos));
|
||||
if (v && SAME_TYPE(SCHEME_TYPE(v), scheme_struct_proc_shape_type)) {
|
||||
int mode = (SCHEME_PROC_SHAPE_MODE(v) & STRUCT_PROC_SHAPE_MASK);
|
||||
int field_count = (SCHEME_PROC_SHAPE_MODE(v) >> STRUCT_PROC_SHAPE_SHIFT);
|
||||
if (mode == STRUCT_PROC_SHAPE_STRUCT)
|
||||
return field_count + 1;
|
||||
}
|
||||
}
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(arg), scheme_toplevel_type)) {
|
||||
pos = SCHEME_TOPLEVEL_POS(arg);
|
||||
if (runstack) {
|
||||
/* This is eval mode; conceptually, this code belongs in
|
||||
define_execute_with_dynamic_state() */
|
||||
Scheme_Bucket *b;
|
||||
Scheme_Prefix *toplevels;
|
||||
toplevels = (Scheme_Prefix *)runstack[SCHEME_TOPLEVEL_DEPTH(arg) - rs_delta];
|
||||
b = (Scheme_Bucket *)toplevels->a[pos];
|
||||
if (b->val) {
|
||||
if (SCHEME_STRUCT_TYPEP(b->val)
|
||||
&& (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_IS_CONSISTENT)) {
|
||||
Scheme_Struct_Type *st = (Scheme_Struct_Type *)b->val;
|
||||
if (st->num_slots == st->num_islots)
|
||||
return st->num_slots + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (symbols) {
|
||||
/* This is module-export mode; conceptually, this code belongs in
|
||||
setup_accessible_table() */
|
||||
Scheme_Object *name;
|
||||
name = symbols[pos];
|
||||
if (SCHEME_SYMBOLP(name)) {
|
||||
v = scheme_hash_get(symbol_table, name);
|
||||
if (v && SCHEME_PAIRP(v)) {
|
||||
v = SCHEME_CDR(v);
|
||||
if (v && SAME_TYPE(SCHEME_TYPE(v), scheme_struct_proc_shape_type)) {
|
||||
int mode = (SCHEME_PROC_SHAPE_MODE(v) & STRUCT_PROC_SHAPE_MASK);
|
||||
int field_count = (SCHEME_PROC_SHAPE_MODE(v) >> STRUCT_PROC_SHAPE_SHIFT);
|
||||
if (mode == STRUCT_PROC_SHAPE_STRUCT)
|
||||
return field_count + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (top_level_table) {
|
||||
/* This is validate mode; conceptually, this code belongs in
|
||||
define_values_validate() */
|
||||
v = scheme_hash_get(top_level_table, scheme_make_integer(pos));
|
||||
if (v)
|
||||
return SCHEME_INT_VAL(v) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved,
|
||||
int check_auto,
|
||||
GC_CAN_IGNORE int *_auto_e_depth,
|
||||
int *_field_count, int *_init_field_count,
|
||||
int *_uses_super,
|
||||
Scheme_Hash_Table *top_level_consts,
|
||||
Scheme_Hash_Table *top_level_table,
|
||||
Scheme_Object **runstack, int rs_delta,
|
||||
Scheme_Object **symbols, Scheme_Hash_Table *symbol_table,
|
||||
int fuel)
|
||||
/* Checks whether it's a `make-struct-type' call that certainly succeeds
|
||||
(i.e., no exception) --- pending a check of the auto-value argument if !check_auto.
|
||||
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. */
|
||||
{
|
||||
if (!fuel) return NULL;
|
||||
|
||||
if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)) {
|
||||
if ((vals == 5) || (vals < 0)) {
|
||||
Scheme_App_Rec *app = (Scheme_App_Rec *)e;
|
||||
|
||||
if ((app->num_args >= 4) && (app->num_args <= 11)
|
||||
&& SAME_OBJ(scheme_make_struct_type_proc, app->args[0])) {
|
||||
int super_count_plus_one;
|
||||
|
||||
if (!SCHEME_FALSEP(app->args[2]))
|
||||
super_count_plus_one = is_constant_super(app->args[2],
|
||||
top_level_consts, top_level_table, runstack,
|
||||
rs_delta + app->num_args,
|
||||
symbols, symbol_table);
|
||||
else
|
||||
super_count_plus_one = 0;
|
||||
|
||||
if (SCHEME_SYMBOLP(app->args[1])
|
||||
&& SCHEME_FALSEP(app->args[2]) /* super = #f */
|
||||
&& (SCHEME_FALSEP(app->args[2]) /* super */
|
||||
|| super_count_plus_one)
|
||||
&& SCHEME_INTP(app->args[3])
|
||||
&& (SCHEME_INT_VAL(app->args[3]) >= 0)
|
||||
&& SCHEME_INTP(app->args[4])
|
||||
|
@ -528,13 +704,16 @@ int scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved,
|
|||
&& ((app->num_args < 5)
|
||||
/* auto-field value: */
|
||||
|| !check_auto
|
||||
|| scheme_omittable_expr(app->args[5], 1, 3, resolved, NULL, -1, 0))
|
||||
|| scheme_omittable_expr(app->args[5], 1, 3, resolved, NULL, NULL, -1, 0))
|
||||
&& ((app->num_args < 6)
|
||||
/* no properties: */
|
||||
|| SCHEME_NULLP(app->args[6]))
|
||||
&& ((app->num_args < 7)
|
||||
/* inspector: */
|
||||
|| SCHEME_FALSEP(app->args[7])
|
||||
|| (SCHEME_SYMBOLP(app->args[7])
|
||||
&& !strcmp("prefab", SCHEME_SYM_VAL(app->args[7]))
|
||||
&& !SCHEME_SYM_WEIRDP(app->args[7]))
|
||||
|| is_current_inspector_call(app->args[7]))
|
||||
&& ((app->num_args < 8)
|
||||
/* propcedure property: */
|
||||
|
@ -551,7 +730,20 @@ int scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved,
|
|||
/* constructor name: */
|
||||
|| SCHEME_FALSEP(app->args[11])
|
||||
|| SCHEME_SYMBOLP(app->args[11]))) {
|
||||
return 1;
|
||||
int super_count = (super_count_plus_one
|
||||
? (super_count_plus_one - 1)
|
||||
: 0);
|
||||
if (_auto_e_depth)
|
||||
*_auto_e_depth = (resolved ? app->num_args : 0);
|
||||
if (_field_count)
|
||||
*_field_count = SCHEME_INT_VAL(app->args[3]) + super_count;
|
||||
if (_init_field_count)
|
||||
*_init_field_count = (SCHEME_INT_VAL(app->args[3])
|
||||
+ SCHEME_INT_VAL(app->args[4])
|
||||
+ super_count);
|
||||
if (_uses_super)
|
||||
*_uses_super = (super_count_plus_one ? 1 : 0);
|
||||
return ((app->num_args < 5) ? scheme_true : app->args[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -564,12 +756,29 @@ int scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved,
|
|||
if ((lh->count == 5) && (lh->num_clauses == 1)) {
|
||||
if (SAME_TYPE(SCHEME_TYPE(lh->body), scheme_compiled_let_value_type)) {
|
||||
Scheme_Compiled_Let_Value *lv = (Scheme_Compiled_Let_Value *)lh->body;
|
||||
if (SAME_TYPE(SCHEME_TYPE(lv->value), scheme_application_type)
|
||||
&& scheme_is_simple_make_struct_type(lv->value, 5, resolved, check_auto)) {
|
||||
/* We have (let-values ([... (make-struct-type)]) ....), so make sure body
|
||||
just uses `make-struct-field-{accessor,mutator}'. */
|
||||
if (is_values_with_accessors_and_mutators(lv->body, vals, resolved))
|
||||
return 1;
|
||||
if (SAME_TYPE(SCHEME_TYPE(lv->value), scheme_application_type)) {
|
||||
Scheme_Object *auto_e;
|
||||
int ifc;
|
||||
int lh_delta = ((SCHEME_LET_FLAGS(lh) & (SCHEME_LET_RECURSIVE | SCHEME_LET_STAR))
|
||||
? lh->count
|
||||
: 0);
|
||||
auto_e = scheme_is_simple_make_struct_type(lv->value, 5, resolved, check_auto,
|
||||
_auto_e_depth, _field_count, &ifc,
|
||||
_uses_super,
|
||||
top_level_consts, top_level_table,
|
||||
runstack, rs_delta + lh_delta,
|
||||
symbols, symbol_table,
|
||||
fuel-1);
|
||||
if (auto_e) {
|
||||
/* We have (let-values ([... (make-struct-type)]) ....), so make sure body
|
||||
just uses `make-struct-field-{accessor,mutator}'. */
|
||||
if (is_values_with_accessors_and_mutators(lv->body, vals, resolved, ifc)) {
|
||||
if (_auto_e_depth && lh_delta)
|
||||
*_auto_e_depth += lh_delta;
|
||||
if (_init_field_count) *_init_field_count = ifc;
|
||||
return auto_e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -584,20 +793,63 @@ int scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int resolved,
|
|||
if ((lv->position == 0) && (lv->count == 5)) {
|
||||
Scheme_Object *e2;
|
||||
e2 = skip_clears(lv->value);
|
||||
if (SAME_TYPE(SCHEME_TYPE(e2), scheme_application_type)
|
||||
&& scheme_is_simple_make_struct_type(e2, 5, resolved, check_auto)) {
|
||||
/* We have (let-values ([... (make-struct-type)]) ....), so make sure body
|
||||
just uses `make-struct-field-{accessor,mutator}'. */
|
||||
e2 = skip_clears(lv->body);
|
||||
if (is_values_with_accessors_and_mutators(e2, vals, resolved))
|
||||
return 1;
|
||||
if (SAME_TYPE(SCHEME_TYPE(e2), scheme_application_type)) {
|
||||
Scheme_Object *auto_e;
|
||||
int ifc;
|
||||
auto_e = scheme_is_simple_make_struct_type(e2, 5, resolved, check_auto,
|
||||
_auto_e_depth, _field_count, &ifc,
|
||||
_uses_super,
|
||||
top_level_consts, top_level_table,
|
||||
runstack, rs_delta + lvd->count,
|
||||
symbols, symbol_table,
|
||||
fuel-1);
|
||||
if (auto_e) {
|
||||
/* We have (let-values ([... (make-struct-type)]) ....), so make sure body
|
||||
just uses `make-struct-field-{accessor,mutator}'. */
|
||||
e2 = skip_clears(lv->body);
|
||||
if (is_values_with_accessors_and_mutators(e2, vals, resolved, ifc)) {
|
||||
if (_auto_e_depth) *_auto_e_depth += lvd->count;
|
||||
if (_init_field_count) *_init_field_count = ifc;
|
||||
return auto_e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Scheme_Object *scheme_make_struct_proc_shape(int k, int field_count, int init_field_count)
|
||||
{
|
||||
Scheme_Object *ps;
|
||||
|
||||
switch (k) {
|
||||
case 0:
|
||||
if (field_count == init_field_count)
|
||||
k = STRUCT_PROC_SHAPE_STRUCT | (field_count << STRUCT_PROC_SHAPE_SHIFT);
|
||||
else
|
||||
k = STRUCT_PROC_SHAPE_OTHER;
|
||||
break;
|
||||
case 1:
|
||||
k = STRUCT_PROC_SHAPE_CONSTR | (init_field_count << STRUCT_PROC_SHAPE_SHIFT);
|
||||
break;
|
||||
case 2:
|
||||
k = STRUCT_PROC_SHAPE_PRED;
|
||||
break;
|
||||
default:
|
||||
if (struct_proc_shape_other)
|
||||
return struct_proc_shape_other;
|
||||
k = STRUCT_PROC_SHAPE_OTHER;
|
||||
}
|
||||
|
||||
ps = scheme_malloc_small_atomic_tagged(sizeof(Scheme_Small_Object));
|
||||
ps->type = scheme_struct_proc_shape_type;
|
||||
SCHEME_PROC_SHAPE_MODE(ps) = k;
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
||||
|
@ -2039,9 +2291,17 @@ static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimiz
|
|||
}
|
||||
}
|
||||
|
||||
if (SAME_OBJ(scheme_struct_type_p_proc, app->rator)) {
|
||||
Scheme_Object *c;
|
||||
c = get_struct_proc_shape(app->rand, info);
|
||||
if (c && ((SCHEME_PROC_SHAPE_MODE(c) & STRUCT_PROC_SHAPE_MASK)
|
||||
== STRUCT_PROC_SHAPE_STRUCT))
|
||||
return scheme_true;
|
||||
}
|
||||
|
||||
if ((SAME_OBJ(scheme_values_func, app->rator)
|
||||
|| SAME_OBJ(scheme_list_star_proc, app->rator))
|
||||
&& (scheme_omittable_expr(app->rand, 1, -1, 0, info, -1, 0)
|
||||
&& (scheme_omittable_expr(app->rand, 1, -1, 0, info, info, -1, 0)
|
||||
|| single_valued_noncm_expression(app->rand, 5))) {
|
||||
info->preserves_marks = 1;
|
||||
info->single_result = 1;
|
||||
|
@ -2083,13 +2343,13 @@ static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimiz
|
|||
if (SAME_OBJ(scheme_list_proc, app2->rator)) {
|
||||
if (IS_NAMED_PRIM(app->rator, "car")) {
|
||||
/* (car (list X)) */
|
||||
if (scheme_omittable_expr(app2->rand, 1, 5, 0, NULL, -1, 0)
|
||||
if (scheme_omittable_expr(app2->rand, 1, 5, 0, info, NULL, -1, 0)
|
||||
|| single_valued_noncm_expression(app2->rand, 5)) {
|
||||
alt = app2->rand;
|
||||
}
|
||||
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
||||
/* (cdr (list X)) */
|
||||
if (scheme_omittable_expr(app2->rand, 1, 5, 0, NULL, -1, 0))
|
||||
if (scheme_omittable_expr(app2->rand, 1, 5, 0, info, NULL, -1, 0))
|
||||
alt = scheme_null;
|
||||
}
|
||||
}
|
||||
|
@ -2100,27 +2360,27 @@ static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimiz
|
|||
|| SAME_OBJ(scheme_list_proc, app3->rator)
|
||||
|| SAME_OBJ(scheme_list_star_proc, app3->rator)) {
|
||||
/* (car ({cons|list|list*} X Y)) */
|
||||
if ((scheme_omittable_expr(app3->rand1, 1, 5, 0, NULL, -1, 0)
|
||||
if ((scheme_omittable_expr(app3->rand1, 1, 5, 0, info, NULL, -1, 0)
|
||||
|| single_valued_noncm_expression(app3->rand1, 5))
|
||||
&& scheme_omittable_expr(app3->rand2, 1, 5, 0, NULL, -1, 0)) {
|
||||
&& scheme_omittable_expr(app3->rand2, 1, 5, 0, info, NULL, -1, 0)) {
|
||||
alt = app3->rand1;
|
||||
}
|
||||
}
|
||||
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
||||
/* (cdr (cons X Y)) */
|
||||
if (SAME_OBJ(scheme_cons_proc, app3->rator)) {
|
||||
if ((scheme_omittable_expr(app3->rand2, 1, 5, 0, NULL, -1, 0)
|
||||
if ((scheme_omittable_expr(app3->rand2, 1, 5, 0, info, NULL, -1, 0)
|
||||
|| single_valued_noncm_expression(app3->rand2, 5))
|
||||
&& scheme_omittable_expr(app3->rand1, 1, 5, 0, NULL, -1, 0)) {
|
||||
&& scheme_omittable_expr(app3->rand1, 1, 5, 0, info, NULL, -1, 0)) {
|
||||
alt = app3->rand2;
|
||||
}
|
||||
}
|
||||
} else if (IS_NAMED_PRIM(app->rator, "cadr")) {
|
||||
if (SAME_OBJ(scheme_list_proc, app3->rator)) {
|
||||
/* (cadr (list X Y)) */
|
||||
if ((scheme_omittable_expr(app3->rand2, 1, 5, 0, NULL, -1, 0)
|
||||
if ((scheme_omittable_expr(app3->rand2, 1, 5, 0, info, NULL, -1, 0)
|
||||
|| single_valued_noncm_expression(app3->rand2, 5))
|
||||
&& scheme_omittable_expr(app3->rand1, 1, 5, 0, NULL, -1, 0)) {
|
||||
&& scheme_omittable_expr(app3->rand1, 1, 5, 0, info, NULL, -1, 0)) {
|
||||
alt = app3->rand2;
|
||||
}
|
||||
}
|
||||
|
@ -2472,7 +2732,7 @@ static Scheme_Object *optimize_sequence(Scheme_Object *o, Optimize_Info *info, i
|
|||
/* Inlining and constant propagation can expose
|
||||
omittable expressions. */
|
||||
if ((i + 1 != count)
|
||||
&& scheme_omittable_expr(le, -1, -1, 0, NULL, -1, 0)) {
|
||||
&& scheme_omittable_expr(le, -1, -1, 0, info, NULL, -1, 0)) {
|
||||
drop++;
|
||||
info->size = prev_size;
|
||||
s->array[i] = NULL;
|
||||
|
@ -2655,7 +2915,7 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
|
|||
}
|
||||
|
||||
/* Try optimize: (if <omitable-expr> v v) => v */
|
||||
if (scheme_omittable_expr(t, 1, 20, 0, NULL, -1, 0)
|
||||
if (scheme_omittable_expr(t, 1, 20, 0, info, NULL, -1, 0)
|
||||
&& equivalent_exprs(tb, fb)) {
|
||||
info->size -= 2; /* could be more precise */
|
||||
return tb;
|
||||
|
@ -2697,7 +2957,7 @@ static int omittable_key(Scheme_Object *k, Optimize_Info *info)
|
|||
{
|
||||
/* A key is not omittable if it might refer to a chaperoned/impersonated
|
||||
continuation mark key, so that's why we pass 1 for `no_id': */
|
||||
return scheme_omittable_expr(k, 1, 20, 0, info, -1, 1);
|
||||
return scheme_omittable_expr(k, 1, 20, 0, info, info, -1, 1);
|
||||
}
|
||||
|
||||
static Scheme_Object *optimize_wcm(Scheme_Object *o, Optimize_Info *info, int context)
|
||||
|
@ -2712,8 +2972,8 @@ static Scheme_Object *optimize_wcm(Scheme_Object *o, Optimize_Info *info, int co
|
|||
b = scheme_optimize_expr(wcm->body, info, scheme_optimize_tail_context(context));
|
||||
|
||||
if (omittable_key(k, info)
|
||||
&& scheme_omittable_expr(v, 1, 20, 0, info, -1, 0)
|
||||
&& scheme_omittable_expr(b, -1, 20, 0, info, -1, 0))
|
||||
&& scheme_omittable_expr(v, 1, 20, 0, info, info, -1, 0)
|
||||
&& scheme_omittable_expr(b, -1, 20, 0, info, info, -1, 0))
|
||||
return b;
|
||||
|
||||
/* info->single_result is already set */
|
||||
|
@ -3030,17 +3290,53 @@ case_lambda_shift(Scheme_Object *data, int delta, int after_depth)
|
|||
static Scheme_Object *
|
||||
begin0_optimize(Scheme_Object *obj, Optimize_Info *info, int context)
|
||||
{
|
||||
int i, count;
|
||||
int i, count, drop = 0, prev_size;
|
||||
Scheme_Sequence *s = (Scheme_Sequence *)obj;
|
||||
Scheme_Object *le;
|
||||
|
||||
count = ((Scheme_Sequence *)obj)->count;
|
||||
count = s->count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
Scheme_Object *le;
|
||||
le = scheme_optimize_expr(((Scheme_Sequence *)obj)->array[i], info,
|
||||
prev_size = info->size;
|
||||
|
||||
le = scheme_optimize_expr(s->array[i],
|
||||
info,
|
||||
(!i
|
||||
? scheme_optimize_result_context(context)
|
||||
: 0));
|
||||
((Scheme_Sequence *)obj)->array[i] = le;
|
||||
|
||||
/* Inlining and constant propagation can expose
|
||||
omittable expressions. */
|
||||
if (i && scheme_omittable_expr(le, -1, -1, 0, info, NULL, -1, 0)) {
|
||||
drop++;
|
||||
info->size = prev_size;
|
||||
s->array[i] = NULL;
|
||||
} else {
|
||||
s->array[i] = le;
|
||||
}
|
||||
}
|
||||
|
||||
if (drop) {
|
||||
Scheme_Sequence *s2;
|
||||
int j = 0;
|
||||
|
||||
if ((s->count - drop) == 1) {
|
||||
/* can't drop down to 1 expression */
|
||||
s->array[s->count-1] = scheme_false;
|
||||
--drop;
|
||||
}
|
||||
|
||||
s2 = scheme_malloc_sequence(s->count - drop);
|
||||
s2->so.type = s->so.type;
|
||||
s2->count = s->count - drop;
|
||||
|
||||
for (i = 0; i < s->count; i++) {
|
||||
if (s->array[i]) {
|
||||
s2->array[j++] = s->array[i];
|
||||
}
|
||||
}
|
||||
|
||||
obj = (Scheme_Object *)s2;
|
||||
}
|
||||
|
||||
/* Optimization of expression 0 has already set single_result */
|
||||
|
@ -3236,6 +3532,9 @@ int scheme_compiled_propagate_ok(Scheme_Object *value, Optimize_Info *info)
|
|||
pos = SCHEME_TOPLEVEL_POS(value);
|
||||
value = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
|
||||
value = no_potential_size(value);
|
||||
if (SAME_OBJ(value, scheme_constant_key)
|
||||
|| (value && SAME_TYPE(SCHEME_TYPE(value), scheme_struct_proc_shape_type)))
|
||||
return 0;
|
||||
if (value)
|
||||
return 1;
|
||||
}
|
||||
|
@ -3256,7 +3555,7 @@ int scheme_is_statically_proc(Scheme_Object *value, Optimize_Info *info)
|
|||
Scheme_Let_Header *lh = (Scheme_Let_Header *)value;
|
||||
if (lh->num_clauses == 1) {
|
||||
Scheme_Compiled_Let_Value *lv = (Scheme_Compiled_Let_Value *)lh->body;
|
||||
if (scheme_omittable_expr(lv->value, lv->count, 20, 0, NULL, -1, 0)) {
|
||||
if (scheme_omittable_expr(lv->value, lv->count, 20, 0, info, NULL, -1, 0)) {
|
||||
value = lv->body;
|
||||
info = NULL;
|
||||
} else
|
||||
|
@ -3819,7 +4118,7 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
|
|||
if ((pre_body->count != 1)
|
||||
&& is_values_apply(value, pre_body->count)
|
||||
&& ((!is_rec && no_mutable_bindings(pre_body))
|
||||
|| scheme_omittable_expr(value, pre_body->count, -1, 0, info,
|
||||
|| scheme_omittable_expr(value, pre_body->count, -1, 0, info, info,
|
||||
(is_rec
|
||||
? (pre_body->position + pre_body->count)
|
||||
: -1),
|
||||
|
@ -4202,7 +4501,7 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
|
|||
}
|
||||
|
||||
if (!used
|
||||
&& (scheme_omittable_expr(pre_body->value, pre_body->count, -1, 0, info, -1, 0)
|
||||
&& (scheme_omittable_expr(pre_body->value, pre_body->count, -1, 0, info, info, -1, 0)
|
||||
|| ((pre_body->count == 1)
|
||||
&& first_once_used
|
||||
&& (first_once_used->pos == pos)
|
||||
|
@ -4630,7 +4929,7 @@ static Scheme_Object *is_cross_module_inline_candidiate(Scheme_Object *e, Optimi
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int is_general_compiled_proc(Scheme_Object *e)
|
||||
static int is_general_compiled_proc(Scheme_Object *e, Optimize_Info *info)
|
||||
{
|
||||
/* recognize (begin <omitable>* <proc>) */
|
||||
if (SCHEME_TYPE(e) == scheme_sequence_type) {
|
||||
|
@ -4638,7 +4937,7 @@ static int is_general_compiled_proc(Scheme_Object *e)
|
|||
if (seq->count > 0) {
|
||||
int i;
|
||||
for (i = seq->count - 1; i--; ) {
|
||||
if (!scheme_omittable_expr(seq->array[i], -1, 20, 0, NULL, -1, 0))
|
||||
if (!scheme_omittable_expr(seq->array[i], -1, 20, 0, info, NULL, -1, 0))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -4739,7 +5038,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
|
||||
Scheme_Object *e2;
|
||||
e2 = SCHEME_VEC_ELS(e)[1];
|
||||
if (is_general_compiled_proc(e2))
|
||||
if (is_general_compiled_proc(e2, info))
|
||||
is_proc_def = 1;
|
||||
}
|
||||
}
|
||||
|
@ -4763,13 +5062,19 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
(including raising an exception), then continue the group of
|
||||
simultaneous definitions: */
|
||||
if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
|
||||
int n, cnst = 0, sproc = 0;
|
||||
int n, cnst = 0, sproc = 0, sstruct = 0, field_count = 0, init_field_count = 0;
|
||||
|
||||
vars = SCHEME_VEC_ELS(e)[0];
|
||||
e = SCHEME_VEC_ELS(e)[1];
|
||||
|
||||
n = scheme_list_length(vars);
|
||||
cont = scheme_omittable_expr(e, n, -1, 0, info, -1, 0);
|
||||
cont = scheme_omittable_expr(e, n, -1, 0,
|
||||
/* no `info' here, because the decision
|
||||
of omittable should not depend on
|
||||
information that's only available at
|
||||
optimization time: */
|
||||
NULL,
|
||||
info, -1, 0);
|
||||
|
||||
if (n == 1) {
|
||||
if (scheme_compiled_propagate_ok(e, info))
|
||||
|
@ -4778,20 +5083,28 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
cnst = 1;
|
||||
sproc = 1;
|
||||
}
|
||||
} else if (scheme_is_simple_make_struct_type(e, n, 0, 1)) {
|
||||
} else if (scheme_is_simple_make_struct_type(e, n, 0, 1, NULL,
|
||||
&field_count, &init_field_count, NULL,
|
||||
info->top_level_consts,
|
||||
NULL, NULL, 0, NULL, NULL,
|
||||
5)) {
|
||||
sstruct = 1;
|
||||
cnst = 1;
|
||||
}
|
||||
|
||||
if (cnst) {
|
||||
Scheme_Toplevel *tl;
|
||||
while (n--) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
tl = (Scheme_Toplevel *)SCHEME_CAR(vars);
|
||||
vars = SCHEME_CDR(vars);
|
||||
|
||||
if (!(SCHEME_TOPLEVEL_FLAGS(tl) & SCHEME_TOPLEVEL_MUTATED)) {
|
||||
Scheme_Object *e2;
|
||||
|
||||
if (sproc) {
|
||||
if (sstruct) {
|
||||
e2 = scheme_make_struct_proc_shape(i, field_count, init_field_count);
|
||||
} else if (sproc) {
|
||||
e2 = scheme_make_noninline_proc(e);
|
||||
} else if (IS_COMPILED_PROC(e)) {
|
||||
e2 = optimize_clone(1, e, info, 0, 0);
|
||||
|
@ -4811,17 +5124,27 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
|
||||
if (e2) {
|
||||
int pos;
|
||||
if (!consts)
|
||||
consts = scheme_make_hash_table(SCHEME_hash_ptr);
|
||||
pos = tl->position;
|
||||
scheme_hash_set(consts, scheme_make_integer(pos), e2);
|
||||
if (!re_consts)
|
||||
re_consts = scheme_make_hash_table(SCHEME_hash_ptr);
|
||||
scheme_hash_set(re_consts, scheme_make_integer(i_m),
|
||||
scheme_make_integer(pos));
|
||||
if (sstruct) {
|
||||
/* Add directly to `info->top_level_consts' for use
|
||||
by sub-struct declarations in the same set */
|
||||
if (!info->top_level_consts) {
|
||||
Scheme_Hash_Table *tlc;
|
||||
tlc = scheme_make_hash_table(SCHEME_hash_ptr);
|
||||
info->top_level_consts = tlc;
|
||||
}
|
||||
scheme_hash_set(info->top_level_consts, scheme_make_integer(pos), e2);
|
||||
} else {
|
||||
if (!consts)
|
||||
consts = scheme_make_hash_table(SCHEME_hash_ptr);
|
||||
scheme_hash_set(consts, scheme_make_integer(pos), e2);
|
||||
if (!re_consts)
|
||||
re_consts = scheme_make_hash_table(SCHEME_hash_ptr);
|
||||
scheme_hash_set(re_consts, scheme_make_integer(i_m),
|
||||
scheme_make_integer(pos));
|
||||
}
|
||||
} else {
|
||||
/* At least mark it as fixed */
|
||||
|
||||
if (!fixed_table) {
|
||||
fixed_table = scheme_make_hash_table(SCHEME_hash_ptr);
|
||||
if (!consts)
|
||||
|
@ -4851,7 +5174,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
cont = scheme_omittable_expr(e, -1, -1, 0, NULL, -1, 0);
|
||||
cont = scheme_omittable_expr(e, -1, -1, 0, NULL, NULL, -1, 0);
|
||||
}
|
||||
if (i_m + 1 == cnt)
|
||||
cont = 0;
|
||||
|
@ -5025,7 +5348,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
for (i_m = 0; i_m < cnt; i_m++) {
|
||||
/* Optimize this expression: */
|
||||
e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
|
||||
if (scheme_omittable_expr(e, -1, -1, 0, NULL, -1, 0)) {
|
||||
if (scheme_omittable_expr(e, -1, -1, 0, info, NULL, -1, 0)) {
|
||||
can_omit++;
|
||||
}
|
||||
}
|
||||
|
@ -5036,7 +5359,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
for (i_m = 0; i_m < cnt; i_m++) {
|
||||
/* Optimize this expression: */
|
||||
e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
|
||||
if (!scheme_omittable_expr(e, -1, -1, 0, NULL, -1, 0)) {
|
||||
if (!scheme_omittable_expr(e, -1, -1, 0, info, NULL, -1, 0)) {
|
||||
SCHEME_VEC_ELS(vec)[j++] = e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ static Scheme_Object *look_for_letv_change(Scheme_Sequence *s)
|
|||
v = s->array[i];
|
||||
if (SAME_TYPE(SCHEME_TYPE(v), scheme_let_value_type)) {
|
||||
Scheme_Let_Value *lv = (Scheme_Let_Value *)v;
|
||||
if (scheme_omittable_expr(lv->body, 1, -1, 0, NULL, -1, 0)) {
|
||||
if (scheme_omittable_expr(lv->body, 1, -1, 0, NULL, NULL, -1, 0)) {
|
||||
int esize = s->count - (i + 1);
|
||||
int nsize = i + 1;
|
||||
Scheme_Object *nv, *ev;
|
||||
|
@ -1240,7 +1240,7 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
|
|||
}
|
||||
if (j >= 0)
|
||||
break;
|
||||
if (!scheme_omittable_expr(clv->value, clv->count, -1, 0, NULL, -1, 0))
|
||||
if (!scheme_omittable_expr(clv->value, clv->count, -1, 0, NULL, NULL, -1, 0))
|
||||
break;
|
||||
}
|
||||
if (i < 0) {
|
||||
|
|
|
@ -373,6 +373,7 @@ extern Scheme_Object *scheme_call_with_values_proc;
|
|||
extern Scheme_Object *scheme_make_struct_type_proc;
|
||||
extern Scheme_Object *scheme_make_struct_field_accessor_proc;
|
||||
extern Scheme_Object *scheme_make_struct_field_mutator_proc;
|
||||
extern Scheme_Object *scheme_struct_type_p_proc;
|
||||
extern Scheme_Object *scheme_current_inspector_proc;
|
||||
extern Scheme_Object *scheme_varref_const_p_proc;
|
||||
|
||||
|
@ -2860,11 +2861,28 @@ int scheme_used_app_only(Scheme_Comp_Env *env, int which);
|
|||
int scheme_used_ever(Scheme_Comp_Env *env, int which);
|
||||
|
||||
int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
||||
Optimize_Info *warn_info, int deeper_than, int no_id);
|
||||
Optimize_Info *opt_info, Optimize_Info *warn_info, int deeper_than, int no_id);
|
||||
int scheme_might_invoke_call_cc(Scheme_Object *value);
|
||||
int scheme_is_liftable(Scheme_Object *o, int bind_count, int fuel, int as_rator);
|
||||
int scheme_is_functional_primitive(Scheme_Object *rator, int num_args, int expected_vals);
|
||||
int scheme_is_simple_make_struct_type(Scheme_Object *app, int vals, int resolved, int check_auto);
|
||||
Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *app, int vals, int resolved,
|
||||
int check_auto, int *_auto_e_depth,
|
||||
int *_field_count, int *_init_field_count,
|
||||
int *_uses_super,
|
||||
Scheme_Hash_Table *top_level_consts,
|
||||
Scheme_Hash_Table *top_level_table,
|
||||
Scheme_Object **runstack, int rs_delta,
|
||||
Scheme_Object **symbols, Scheme_Hash_Table *symbol_table,
|
||||
int fuel);
|
||||
|
||||
Scheme_Object *scheme_make_struct_proc_shape(int k, int field_count, int init_field_count);
|
||||
#define STRUCT_PROC_SHAPE_STRUCT 0
|
||||
#define STRUCT_PROC_SHAPE_PRED 1
|
||||
#define STRUCT_PROC_SHAPE_OTHER 2
|
||||
#define STRUCT_PROC_SHAPE_CONSTR 3
|
||||
#define STRUCT_PROC_SHAPE_MASK 0x7
|
||||
#define STRUCT_PROC_SHAPE_SHIFT 3
|
||||
#define SCHEME_PROC_SHAPE_MODE(obj) (((Scheme_Small_Object *)(obj))->u.int_val)
|
||||
|
||||
int scheme_is_env_variable_boxed(Scheme_Comp_Env *env, int which);
|
||||
|
||||
|
|
|
@ -671,7 +671,7 @@ static Scheme_Object *sfs_let_one(Scheme_Object *o, SFS_Info *info)
|
|||
it might not because (1) it was introduced late by inlining,
|
||||
or (2) the rhs expression doesn't always produce a single
|
||||
value. */
|
||||
if (scheme_omittable_expr(rhs, 1, -1, 1, NULL, -1, 0)) {
|
||||
if (scheme_omittable_expr(rhs, 1, -1, 1, NULL, NULL, -1, 0)) {
|
||||
rhs = scheme_false;
|
||||
} else if ((ip < info->max_calls[pos])
|
||||
&& SAME_TYPE(SCHEME_TYPE(rhs), scheme_toplevel_type)) {
|
||||
|
|
|
@ -38,6 +38,7 @@ READ_ONLY Scheme_Object *scheme_impersonator_of_property;
|
|||
READ_ONLY Scheme_Object *scheme_make_struct_type_proc;
|
||||
READ_ONLY Scheme_Object *scheme_make_struct_field_accessor_proc;
|
||||
READ_ONLY Scheme_Object *scheme_make_struct_field_mutator_proc;
|
||||
READ_ONLY Scheme_Object *scheme_struct_type_p_proc;
|
||||
READ_ONLY Scheme_Object *scheme_current_inspector_proc;
|
||||
READ_ONLY Scheme_Object *scheme_recur_symbol;
|
||||
READ_ONLY Scheme_Object *scheme_display_symbol;
|
||||
|
@ -607,11 +608,13 @@ scheme_init_struct (Scheme_Env *env)
|
|||
"struct?",
|
||||
1, 1, 1),
|
||||
env);
|
||||
scheme_add_global_constant("struct-type?",
|
||||
scheme_make_folding_prim(struct_type_p,
|
||||
"struct-type?",
|
||||
1, 1, 1),
|
||||
env);
|
||||
|
||||
REGISTER_SO(scheme_struct_type_p_proc);
|
||||
scheme_struct_type_p_proc = scheme_make_folding_prim(struct_type_p,
|
||||
"struct-type?",
|
||||
1, 1, 1);
|
||||
scheme_add_global_constant("struct-type?", scheme_struct_type_p_proc, env);
|
||||
|
||||
scheme_add_global_constant("struct-type-property?",
|
||||
scheme_make_folding_prim(struct_type_property_p,
|
||||
"struct-type-property?",
|
||||
|
|
|
@ -198,83 +198,84 @@ enum {
|
|||
scheme_serialized_tcp_fd_type, /* 178 */
|
||||
scheme_serialized_file_fd_type, /* 179 */
|
||||
scheme_port_closed_evt_type, /* 180 */
|
||||
scheme_struct_proc_shape_type, /* 181 */
|
||||
|
||||
#ifdef MZTAG_REQUIRED
|
||||
_scheme_last_normal_type_, /* 181 */
|
||||
_scheme_last_normal_type_, /* 182 */
|
||||
|
||||
scheme_rt_weak_array, /* 182 */
|
||||
scheme_rt_weak_array, /* 183 */
|
||||
|
||||
scheme_rt_comp_env, /* 183 */
|
||||
scheme_rt_constant_binding, /* 184 */
|
||||
scheme_rt_resolve_info, /* 185 */
|
||||
scheme_rt_unresolve_info, /* 186 */
|
||||
scheme_rt_optimize_info, /* 187 */
|
||||
scheme_rt_compile_info, /* 188 */
|
||||
scheme_rt_cont_mark, /* 189 */
|
||||
scheme_rt_saved_stack, /* 190 */
|
||||
scheme_rt_reply_item, /* 191 */
|
||||
scheme_rt_closure_info, /* 192 */
|
||||
scheme_rt_overflow, /* 193 */
|
||||
scheme_rt_overflow_jmp, /* 194 */
|
||||
scheme_rt_meta_cont, /* 195 */
|
||||
scheme_rt_dyn_wind_cell, /* 196 */
|
||||
scheme_rt_dyn_wind_info, /* 197 */
|
||||
scheme_rt_dyn_wind, /* 198 */
|
||||
scheme_rt_dup_check, /* 199 */
|
||||
scheme_rt_thread_memory, /* 200 */
|
||||
scheme_rt_input_file, /* 201 */
|
||||
scheme_rt_input_fd, /* 202 */
|
||||
scheme_rt_oskit_console_input, /* 203 */
|
||||
scheme_rt_tested_input_file, /* 204 */
|
||||
scheme_rt_tested_output_file, /* 205 */
|
||||
scheme_rt_indexed_string, /* 206 */
|
||||
scheme_rt_output_file, /* 207 */
|
||||
scheme_rt_load_handler_data, /* 208 */
|
||||
scheme_rt_pipe, /* 209 */
|
||||
scheme_rt_beos_process, /* 210 */
|
||||
scheme_rt_system_child, /* 211 */
|
||||
scheme_rt_tcp, /* 212 */
|
||||
scheme_rt_write_data, /* 213 */
|
||||
scheme_rt_tcp_select_info, /* 214 */
|
||||
scheme_rt_param_data, /* 215 */
|
||||
scheme_rt_will, /* 216 */
|
||||
scheme_rt_linker_name, /* 217 */
|
||||
scheme_rt_param_map, /* 218 */
|
||||
scheme_rt_finalization, /* 219 */
|
||||
scheme_rt_finalizations, /* 220 */
|
||||
scheme_rt_cpp_object, /* 221 */
|
||||
scheme_rt_cpp_array_object, /* 222 */
|
||||
scheme_rt_stack_object, /* 223 */
|
||||
scheme_rt_preallocated_object, /* 224 */
|
||||
scheme_thread_hop_type, /* 225 */
|
||||
scheme_rt_srcloc, /* 226 */
|
||||
scheme_rt_evt, /* 227 */
|
||||
scheme_rt_syncing, /* 228 */
|
||||
scheme_rt_comp_prefix, /* 229 */
|
||||
scheme_rt_user_input, /* 230 */
|
||||
scheme_rt_user_output, /* 231 */
|
||||
scheme_rt_compact_port, /* 232 */
|
||||
scheme_rt_read_special_dw, /* 233 */
|
||||
scheme_rt_regwork, /* 234 */
|
||||
scheme_rt_rx_lazy_string, /* 235 */
|
||||
scheme_rt_buf_holder, /* 236 */
|
||||
scheme_rt_parameterization, /* 237 */
|
||||
scheme_rt_print_params, /* 238 */
|
||||
scheme_rt_read_params, /* 239 */
|
||||
scheme_rt_native_code, /* 240 */
|
||||
scheme_rt_native_code_plus_case, /* 241 */
|
||||
scheme_rt_jitter_data, /* 242 */
|
||||
scheme_rt_module_exports, /* 243 */
|
||||
scheme_rt_delay_load_info, /* 244 */
|
||||
scheme_rt_marshal_info, /* 245 */
|
||||
scheme_rt_unmarshal_info, /* 246 */
|
||||
scheme_rt_runstack, /* 247 */
|
||||
scheme_rt_sfs_info, /* 248 */
|
||||
scheme_rt_validate_clearing, /* 249 */
|
||||
scheme_rt_avl_node, /* 250 */
|
||||
scheme_rt_lightweight_cont, /* 251 */
|
||||
scheme_rt_export_info, /* 252 */
|
||||
scheme_rt_cont_jmp, /* 253 */
|
||||
scheme_rt_comp_env, /* 184 */
|
||||
scheme_rt_constant_binding, /* 185 */
|
||||
scheme_rt_resolve_info, /* 186 */
|
||||
scheme_rt_unresolve_info, /* 187 */
|
||||
scheme_rt_optimize_info, /* 188 */
|
||||
scheme_rt_compile_info, /* 189 */
|
||||
scheme_rt_cont_mark, /* 190 */
|
||||
scheme_rt_saved_stack, /* 191 */
|
||||
scheme_rt_reply_item, /* 192 */
|
||||
scheme_rt_closure_info, /* 193 */
|
||||
scheme_rt_overflow, /* 194 */
|
||||
scheme_rt_overflow_jmp, /* 195 */
|
||||
scheme_rt_meta_cont, /* 196 */
|
||||
scheme_rt_dyn_wind_cell, /* 197 */
|
||||
scheme_rt_dyn_wind_info, /* 198 */
|
||||
scheme_rt_dyn_wind, /* 199 */
|
||||
scheme_rt_dup_check, /* 200 */
|
||||
scheme_rt_thread_memory, /* 201 */
|
||||
scheme_rt_input_file, /* 202 */
|
||||
scheme_rt_input_fd, /* 203 */
|
||||
scheme_rt_oskit_console_input, /* 204 */
|
||||
scheme_rt_tested_input_file, /* 205 */
|
||||
scheme_rt_tested_output_file, /* 206 */
|
||||
scheme_rt_indexed_string, /* 207 */
|
||||
scheme_rt_output_file, /* 208 */
|
||||
scheme_rt_load_handler_data, /* 209 */
|
||||
scheme_rt_pipe, /* 210 */
|
||||
scheme_rt_beos_process, /* 211 */
|
||||
scheme_rt_system_child, /* 212 */
|
||||
scheme_rt_tcp, /* 213 */
|
||||
scheme_rt_write_data, /* 214 */
|
||||
scheme_rt_tcp_select_info, /* 215 */
|
||||
scheme_rt_param_data, /* 216 */
|
||||
scheme_rt_will, /* 217 */
|
||||
scheme_rt_linker_name, /* 218 */
|
||||
scheme_rt_param_map, /* 219 */
|
||||
scheme_rt_finalization, /* 220 */
|
||||
scheme_rt_finalizations, /* 221 */
|
||||
scheme_rt_cpp_object, /* 222 */
|
||||
scheme_rt_cpp_array_object, /* 223 */
|
||||
scheme_rt_stack_object, /* 224 */
|
||||
scheme_rt_preallocated_object, /* 225 */
|
||||
scheme_thread_hop_type, /* 226 */
|
||||
scheme_rt_srcloc, /* 227 */
|
||||
scheme_rt_evt, /* 228 */
|
||||
scheme_rt_syncing, /* 229 */
|
||||
scheme_rt_comp_prefix, /* 230 */
|
||||
scheme_rt_user_input, /* 231 */
|
||||
scheme_rt_user_output, /* 232 */
|
||||
scheme_rt_compact_port, /* 233 */
|
||||
scheme_rt_read_special_dw, /* 234 */
|
||||
scheme_rt_regwork, /* 235 */
|
||||
scheme_rt_rx_lazy_string, /* 236 */
|
||||
scheme_rt_buf_holder, /* 237 */
|
||||
scheme_rt_parameterization, /* 238 */
|
||||
scheme_rt_print_params, /* 239 */
|
||||
scheme_rt_read_params, /* 240 */
|
||||
scheme_rt_native_code, /* 241 */
|
||||
scheme_rt_native_code_plus_case, /* 242 */
|
||||
scheme_rt_jitter_data, /* 243 */
|
||||
scheme_rt_module_exports, /* 244 */
|
||||
scheme_rt_delay_load_info, /* 245 */
|
||||
scheme_rt_marshal_info, /* 246 */
|
||||
scheme_rt_unmarshal_info, /* 247 */
|
||||
scheme_rt_runstack, /* 248 */
|
||||
scheme_rt_sfs_info, /* 249 */
|
||||
scheme_rt_validate_clearing, /* 250 */
|
||||
scheme_rt_avl_node, /* 251 */
|
||||
scheme_rt_lightweight_cont, /* 252 */
|
||||
scheme_rt_export_info, /* 253 */
|
||||
scheme_rt_cont_jmp, /* 254 */
|
||||
#endif
|
||||
|
||||
_scheme_last_type_
|
||||
|
|
|
@ -594,7 +594,7 @@ void scheme_register_traversers(void)
|
|||
GC_REG_TRAV(scheme_escaping_cont_type, escaping_cont_proc);
|
||||
GC_REG_TRAV(scheme_rt_cont_jmp, cont_jmp_proc);
|
||||
|
||||
GC_REG_TRAV(scheme_char_type, char_obj);
|
||||
GC_REG_TRAV(scheme_char_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_integer_type, bad_trav);
|
||||
GC_REG_TRAV(scheme_bignum_type, bignum_obj);
|
||||
GC_REG_TRAV(scheme_rational_type, rational_obj);
|
||||
|
@ -611,7 +611,7 @@ void scheme_register_traversers(void)
|
|||
GC_REG_TRAV(scheme_place_dead_type, small_object);
|
||||
#endif
|
||||
GC_REG_TRAV(scheme_keyword_type, symbol_obj);
|
||||
GC_REG_TRAV(scheme_null_type, char_obj); /* small */
|
||||
GC_REG_TRAV(scheme_null_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_pair_type, cons_cell);
|
||||
GC_REG_TRAV(scheme_mutable_pair_type, cons_cell);
|
||||
GC_REG_TRAV(scheme_raw_pair_type, cons_cell);
|
||||
|
@ -624,10 +624,10 @@ void scheme_register_traversers(void)
|
|||
|
||||
GC_REG_TRAV(scheme_input_port_type, input_port);
|
||||
GC_REG_TRAV(scheme_output_port_type, output_port);
|
||||
GC_REG_TRAV(scheme_eof_type, char_obj); /* small */
|
||||
GC_REG_TRAV(scheme_true_type, char_obj); /* small */
|
||||
GC_REG_TRAV(scheme_false_type, char_obj); /* small */
|
||||
GC_REG_TRAV(scheme_void_type, char_obj); /* small */
|
||||
GC_REG_TRAV(scheme_eof_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_true_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_false_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_void_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_syntax_compiler_type, syntax_compiler);
|
||||
GC_REG_TRAV(scheme_macro_type, small_object);
|
||||
GC_REG_TRAV(scheme_box_type, small_object);
|
||||
|
@ -654,7 +654,7 @@ void scheme_register_traversers(void)
|
|||
|
||||
GC_REG_TRAV(scheme_eval_waiting_type, bad_trav);
|
||||
GC_REG_TRAV(scheme_tail_call_waiting_type, bad_trav);
|
||||
GC_REG_TRAV(scheme_undefined_type, char_obj); /* small */
|
||||
GC_REG_TRAV(scheme_undefined_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_placeholder_type, small_object);
|
||||
GC_REG_TRAV(scheme_table_placeholder_type, iptr_obj);
|
||||
|
||||
|
@ -673,9 +673,9 @@ void scheme_register_traversers(void)
|
|||
GC_REG_TRAV(scheme_security_guard_type, guard_val);
|
||||
|
||||
GC_REG_TRAV(scheme_nack_evt_type, twoptr_obj);
|
||||
GC_REG_TRAV(scheme_always_evt_type, char_obj);
|
||||
GC_REG_TRAV(scheme_never_evt_type, char_obj);
|
||||
GC_REG_TRAV(scheme_thread_recv_evt_type, char_obj);
|
||||
GC_REG_TRAV(scheme_always_evt_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_never_evt_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_thread_recv_evt_type, small_atomic_obj);
|
||||
GC_REG_TRAV(scheme_port_closed_evt_type, small_object);
|
||||
|
||||
GC_REG_TRAV(scheme_inspector_type, mark_inspector);
|
||||
|
@ -709,6 +709,8 @@ void scheme_register_traversers(void)
|
|||
GC_REG_TRAV(scheme_rib_delimiter_type, small_object);
|
||||
GC_REG_TRAV(scheme_noninline_proc_type, small_object);
|
||||
GC_REG_TRAV(scheme_prune_context_type, small_object);
|
||||
|
||||
GC_REG_TRAV(scheme_struct_proc_shape_type, small_atomic_obj);
|
||||
}
|
||||
|
||||
END_XFORM_SKIP;
|
||||
|
|
|
@ -42,7 +42,8 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
Scheme_Object *app_rator, int proc_with_refs_ok,
|
||||
int result_ignored, struct Validate_Clearing *vc,
|
||||
int tailpos, int need_flonum, Scheme_Hash_Tree *procs,
|
||||
int expected_results);
|
||||
int expected_results,
|
||||
Scheme_Hash_Table **_st_ht);
|
||||
static int validate_rator_wants_box(Scheme_Object *app_rator, int pos,
|
||||
int hope,
|
||||
Validate_TLS tls,
|
||||
|
@ -132,6 +133,7 @@ void scheme_validate_code(Mz_CPort *port, Scheme_Object *code,
|
|||
struct Validate_Clearing *vc;
|
||||
Validate_TLS tls;
|
||||
mzshort *tl_state;
|
||||
Scheme_Hash_Table *st_ht = NULL;
|
||||
|
||||
depth += ((num_toplevels || num_stxes || num_lifts) ? 1 : 0);
|
||||
|
||||
|
@ -188,7 +190,7 @@ void scheme_validate_code(Mz_CPort *port, Scheme_Object *code,
|
|||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0,
|
||||
vc, 1, 0, NULL, -1)) {
|
||||
vc, 1, 0, NULL, -1, &st_ht)) {
|
||||
tl_timestamp++;
|
||||
if (0) {
|
||||
printf("increment to %d for %d %p\n", tl_timestamp,
|
||||
|
@ -204,7 +206,7 @@ void scheme_validate_code(Mz_CPort *port, Scheme_Object *code,
|
|||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, 0,
|
||||
NULL, 0, 0,
|
||||
vc, 1, 0, NULL, -1);
|
||||
vc, 1, 0, NULL, -1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +244,7 @@ static int validate_toplevel(Scheme_Object *expr, Mz_CPort *port,
|
|||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, skip_refs_check ? 1 : 0, 0,
|
||||
make_clearing_stack(), 0, 0, NULL, 1);
|
||||
make_clearing_stack(), 0, 0, NULL, 1, NULL);
|
||||
}
|
||||
|
||||
static int define_values_validate(Scheme_Object *data, Mz_CPort *port,
|
||||
|
@ -253,9 +255,10 @@ static int define_values_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
mzshort *tl_state, mzshort tl_timestamp,
|
||||
int result_ignored,
|
||||
struct Validate_Clearing *vc, int tailpos,
|
||||
Scheme_Hash_Tree *procs)
|
||||
Scheme_Hash_Tree *procs,
|
||||
Scheme_Hash_Table **_st_ht)
|
||||
{
|
||||
int i, size, flags, result;
|
||||
int i, size, flags, result, is_struct, field_count, field_icount, uses_super;
|
||||
Scheme_Object *val, *only_var;
|
||||
|
||||
val = SCHEME_VEC_ELS(data)[0];
|
||||
|
@ -357,14 +360,45 @@ static int define_values_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
only_var = NULL;
|
||||
}
|
||||
|
||||
if (scheme_is_simple_make_struct_type(val, size-1, 1, 1, NULL,
|
||||
&field_count, &field_icount,
|
||||
&uses_super,
|
||||
NULL, (_st_ht ? *_st_ht : NULL),
|
||||
NULL, 0, NULL, NULL, 5)) {
|
||||
/* This set of bindings is constant across invocations, but
|
||||
if `uses_super', we need to increment tl_timestamp for
|
||||
subtype-defining `struct' sequences. */
|
||||
is_struct = 1;
|
||||
} else {
|
||||
is_struct = 0;
|
||||
uses_super = 0;
|
||||
field_count = 0;
|
||||
field_icount = 0;
|
||||
}
|
||||
|
||||
result = validate_expr(port, val, stack, tls,
|
||||
depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
tl_state, tl_timestamp + (uses_super ? 1 : 0),
|
||||
NULL, !!only_var, 0, vc, 0, 0, NULL,
|
||||
size-1);
|
||||
if (scheme_is_simple_make_struct_type(val, size-1, 1, 1))
|
||||
size-1, NULL);
|
||||
|
||||
if (is_struct) {
|
||||
if (_st_ht && (field_count == field_icount)) {
|
||||
/* record `struct:' binding as constant across invocations,
|
||||
so that it can be recognized for sub-struct declarations */
|
||||
if (!*_st_ht) {
|
||||
Scheme_Hash_Table *ht;
|
||||
ht = scheme_make_hash_table_eqv();
|
||||
*_st_ht = ht;
|
||||
}
|
||||
scheme_hash_set(*_st_ht,
|
||||
scheme_make_integer(SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[1])),
|
||||
scheme_make_integer(field_count));
|
||||
}
|
||||
/* In any case, treat the bindings as constant */
|
||||
result = 2;
|
||||
}
|
||||
|
||||
flags = SCHEME_TOPLEVEL_READY;
|
||||
if (result == 2) {
|
||||
|
@ -373,7 +407,7 @@ static int define_values_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
that's good enough for ensuring safety. */
|
||||
flags = SCHEME_TOPLEVEL_CONST;
|
||||
}
|
||||
|
||||
|
||||
for (i = 1; i < size; i++) {
|
||||
int ts = (tl_timestamp + (result ? 0 : 1));
|
||||
if (tl_state) {
|
||||
|
@ -422,7 +456,7 @@ static int set_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
r1 = validate_expr(port, sb->val, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
r2 = validate_toplevel(sb->var, port, stack, tls, depth, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
|
@ -472,12 +506,12 @@ static int apply_values_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
r2 = validate_expr(port, e, stack, tls,
|
||||
depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, -1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, -1, NULL);
|
||||
|
||||
return validate_join(r1, r2);
|
||||
}
|
||||
|
@ -501,12 +535,12 @@ static void inline_variant_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
validate_expr(port, f2, stack, tls,
|
||||
depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
}
|
||||
|
||||
static void case_lambda_validate(Scheme_Object *data, Mz_CPort *port, char *stack, Validate_TLS tls,
|
||||
|
@ -533,7 +567,7 @@ static void case_lambda_validate(Scheme_Object *data, Mz_CPort *port, char *stac
|
|||
validate_expr(port, e, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,7 +598,7 @@ static int bangboxenv_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
return validate_expr(port, SCHEME_PTR2_VAL(data), stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, result_ignored, vc, tailpos, 0, procs, expected_results);
|
||||
NULL, 0, result_ignored, vc, tailpos, 0, procs, expected_results, NULL);
|
||||
}
|
||||
|
||||
static int begin0_validate(Scheme_Object *data, Mz_CPort *port,
|
||||
|
@ -591,7 +625,7 @@ static int begin0_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, i > 0, vc, 0, 0, procs,
|
||||
(i > 0) ? -1 : expected_results);
|
||||
(i > 0) ? -1 : expected_results, NULL);
|
||||
result = validate_join_seq(r, result);
|
||||
}
|
||||
|
||||
|
@ -701,6 +735,7 @@ static Scheme_Object *validate_k(void)
|
|||
struct Validate_Clearing *vc = (struct Validate_Clearing *)p->ku.k.p4;
|
||||
void *tl_use_map = (((void **)p->ku.k.p5)[4]);
|
||||
mzshort *tl_state = (((void **)p->ku.k.p5)[5]);
|
||||
Scheme_Hash_Table **_st_ht = (((void **)p->ku.k.p5)[6]);
|
||||
int r;
|
||||
|
||||
p->ku.k.p1 = NULL;
|
||||
|
@ -714,7 +749,8 @@ static Scheme_Object *validate_k(void)
|
|||
args[3], args[4], args[5], tl_use_map,
|
||||
tl_state, args[10],
|
||||
app_rator, args[6], args[7], vc, args[8],
|
||||
args[9], procs, args[11]);
|
||||
args[9], procs, args[11],
|
||||
_st_ht);
|
||||
|
||||
return scheme_make_integer(r);
|
||||
}
|
||||
|
@ -903,7 +939,7 @@ void scheme_validate_closure(Mz_CPort *port, Scheme_Object *expr,
|
|||
validate_expr(port, data->code, new_stack, tls, sz, sz, base,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 1, 0, procs, -1);
|
||||
NULL, 0, 0, vc, 1, 0, procs, -1, NULL);
|
||||
}
|
||||
|
||||
static Scheme_Hash_Tree *as_nonempty_procs(Scheme_Hash_Tree *procs)
|
||||
|
@ -1142,7 +1178,8 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
int result_ignored,
|
||||
struct Validate_Clearing *vc, int tailpos,
|
||||
int need_flonum, Scheme_Hash_Tree *procs,
|
||||
int expected_results)
|
||||
int expected_results,
|
||||
Scheme_Hash_Table **_st_ht)
|
||||
/* result is 1 if result is `expected_results' values with no
|
||||
exceptions and no use of any non-ready binding; it's 2 if the
|
||||
result is furthermore a "constant" (i.e., the same shape result for
|
||||
|
@ -1158,7 +1195,13 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
Scheme_Object *r;
|
||||
void **pr;
|
||||
int *args;
|
||||
Scheme_Hash_Table **_2st_ht = NULL;
|
||||
|
||||
if (_st_ht) {
|
||||
_2st_ht = MALLOC_N(Scheme_Hash_Table*, 1);
|
||||
*_2st_ht = *_st_ht;
|
||||
}
|
||||
|
||||
args = MALLOC_N_ATOMIC(int, 11);
|
||||
|
||||
p->ku.k.p1 = (void *)port;
|
||||
|
@ -1179,18 +1222,23 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
args[10] = tl_timestamp;
|
||||
args[11] = expected_results;
|
||||
|
||||
pr = MALLOC_N(void*, 5);
|
||||
pr = MALLOC_N(void*, 6);
|
||||
pr[0] = (void *)args;
|
||||
pr[1] = (void *)app_rator;
|
||||
pr[2] = (void *)tls;
|
||||
pr[3] = (void *)procs;
|
||||
pr[4] = tl_use_map;
|
||||
pr[5] = tl_state;
|
||||
pr[6] = _2st_ht;
|
||||
|
||||
p->ku.k.p5 = (void *)pr;
|
||||
|
||||
r = scheme_handle_stack_overflow(validate_k);
|
||||
|
||||
if (_st_ht) {
|
||||
*_st_ht = *_2st_ht;
|
||||
}
|
||||
|
||||
return SCHEME_INT_VAL(r);
|
||||
}
|
||||
#endif
|
||||
|
@ -1406,7 +1454,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, app->args[i], stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
i ? app->args[0] : NULL, i + 1, 0, vc, 0, 0, procs, 1);
|
||||
i ? app->args[0] : NULL, i + 1, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(result, r);
|
||||
}
|
||||
|
||||
|
@ -1414,10 +1462,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
check_self_call_valid(app->args[0], port, vc, delta, stack);
|
||||
|
||||
if (result) {
|
||||
if (scheme_is_simple_make_struct_type((Scheme_Object *)app, expected_results, 1, 1))
|
||||
r = 2;
|
||||
else
|
||||
r = scheme_is_functional_primitive(app->args[0], app->num_args, expected_results);
|
||||
r = scheme_is_functional_primitive(app->args[0], app->num_args, expected_results);
|
||||
result = validate_join(result, r);
|
||||
}
|
||||
}
|
||||
|
@ -1437,12 +1482,12 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, app->rator, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 1, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 1, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(r, result);
|
||||
r = validate_expr(port, app->rand, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
app->rator, 2, 0, vc, 0, 0, procs, 1);
|
||||
app->rator, 2, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(r, result);
|
||||
|
||||
if (tailpos)
|
||||
|
@ -1470,17 +1515,17 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, app->rator, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 1, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 1, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(r, result);
|
||||
r = validate_expr(port, app->rand1, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
app->rator, 2, 0, vc, 0, 0, procs, 1);
|
||||
app->rator, 2, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(r, result);
|
||||
r = validate_expr(port, app->rand2, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
app->rator, 3, 0, vc, 0, 0, procs, 1);
|
||||
app->rator, 3, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(r, result);
|
||||
|
||||
if (tailpos)
|
||||
|
@ -1507,7 +1552,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, seq->array[i], stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 1, vc, 0, 0, procs, -1);
|
||||
NULL, 0, 1, vc, 0, 0, procs, -1, NULL);
|
||||
result = validate_join_seq(result, r);
|
||||
}
|
||||
|
||||
|
@ -1526,7 +1571,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, b->test, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join(r, result);
|
||||
|
||||
/* This is where letlimit is useful. It prevents let-assignment in the
|
||||
|
@ -1539,7 +1584,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, result_ignored, vc, tailpos, 0, procs,
|
||||
expected_results);
|
||||
expected_results, NULL);
|
||||
result = validate_join_seq(result, r);
|
||||
|
||||
/* since we're branchig, the result isn't constant: */
|
||||
|
@ -1583,12 +1628,12 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, wcm->key, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join_seq(result, r);
|
||||
r = validate_expr(port, wcm->val, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
result = validate_join_seq(result, r);
|
||||
|
||||
expr = wcm->body;
|
||||
|
@ -1633,7 +1678,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
r = validate_expr(port, lv->value, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, lv->count);
|
||||
NULL, 0, 0, vc, 0, 0, procs, lv->count, NULL);
|
||||
result = validate_join_seq(r, result);
|
||||
|
||||
/* memset(stack, VALID_NOT, delta); <-- seems unnecessary (and slow) */
|
||||
|
@ -1740,7 +1785,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, SCHEME_LET_EVAL_TYPE(lo) & LET_ONE_FLONUM, procs,
|
||||
1);
|
||||
1, NULL);
|
||||
result = validate_join_seq(r, result);
|
||||
|
||||
#if !CAN_RESET_STACK_SLOT
|
||||
|
@ -1767,7 +1812,8 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
define_values_validate(expr, port, stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
result_ignored, vc, tailpos, procs));
|
||||
result_ignored, vc, tailpos, procs,
|
||||
_st_ht));
|
||||
break;
|
||||
case scheme_define_syntaxes_type:
|
||||
no_flo(need_flonum, port);
|
||||
|
@ -1879,7 +1925,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
validate_expr(port, seq->array[i], stack, tls, depth, letlimit, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
tl_state, tl_timestamp,
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1);
|
||||
NULL, 0, 0, vc, 0, 0, procs, 1, NULL);
|
||||
}
|
||||
} else if (need_flonum) {
|
||||
if (!SCHEME_FLOATP(expr))
|
||||
|
|
Loading…
Reference in New Issue
Block a user