bytecode validator: check "constant" annotations on variable references
Bytecode changes in two small ways to help the validator: * a cross-module variable reference preserves the compiler's annotation on whether the reference is constant, fixed, or other * lifted procedures now appear in the module body just before the definitions that use them, instead of at the beginning of the module body
This commit is contained in:
parent
839408e6f7
commit
e59066debe
|
@ -73,7 +73,7 @@
|
|||
[(? symbol?) (string->symbol (format "_~a" tl))]
|
||||
[(struct global-bucket (name))
|
||||
(string->symbol (format "_~a" name))]
|
||||
[(struct module-variable (modidx sym pos phase))
|
||||
[(struct module-variable (modidx sym pos phase constantness))
|
||||
(if (and (module-path-index? modidx)
|
||||
(let-values ([(n b) (module-path-index-split modidx)])
|
||||
(and (not n) (not b))))
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
(define (compute-new-modvar mv rw)
|
||||
(match mv
|
||||
[(struct module-variable (modidx sym pos phase))
|
||||
[(struct module-variable (modidx sym pos phase constantness))
|
||||
(match rw
|
||||
[(struct modvar-rewrite (self-modidx provide->toplevel))
|
||||
(log-debug (format "Rewriting ~a of ~S" pos (mpi->path* modidx)))
|
||||
|
@ -76,7 +76,7 @@
|
|||
[remap empty])
|
||||
([tl (in-list mod-toplevels)])
|
||||
(match tl
|
||||
[(and mv (struct module-variable (modidx sym pos phase)))
|
||||
[(and mv (struct module-variable (modidx sym pos phase constantness)))
|
||||
(define rw ((current-get-modvar-rewrite) modidx))
|
||||
; XXX We probably don't need to deal with #f phase
|
||||
(unless (or (not phase) (zero? phase))
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
(define new-prefix prefix)
|
||||
; Cache all the mpi paths
|
||||
(for-each (match-lambda
|
||||
[(and mv (struct module-variable (modidx sym pos phase)))
|
||||
[(and mv (struct module-variable (modidx sym pos phase constantness)))
|
||||
(mpi->path! modidx)]
|
||||
[tl
|
||||
(void)])
|
||||
|
|
|
@ -603,10 +603,14 @@
|
|||
(out-byte CPT_FALSE out)]
|
||||
[(? void?)
|
||||
(out-byte CPT_VOID out)]
|
||||
[(struct module-variable (modidx sym pos phase))
|
||||
[(struct module-variable (modidx sym pos phase constantness))
|
||||
(out-byte CPT_MODULE_VAR out)
|
||||
(out-anything modidx out)
|
||||
(out-anything sym out)
|
||||
(case constantness
|
||||
[(constant) (out-number -4 out)]
|
||||
[(fixed) (out-number -5 out)]
|
||||
[else (void)])
|
||||
(unless (zero? phase)
|
||||
(out-number -2 out)
|
||||
(out-number phase out))
|
||||
|
|
|
@ -857,11 +857,21 @@
|
|||
(let ([mod (read-compact cp)]
|
||||
[var (read-compact cp)]
|
||||
[pos (read-compact-number cp)])
|
||||
(let-values ([(mod-phase pos)
|
||||
(if (= pos -2)
|
||||
(values (read-compact-number cp) (read-compact-number cp))
|
||||
(values 0 pos))])
|
||||
(make-module-variable mod var pos mod-phase)))]
|
||||
(let-values ([(flags mod-phase pos)
|
||||
(let loop ([pos pos])
|
||||
(cond
|
||||
[(pos . < . -3)
|
||||
(let ([real-pos (read-compact-number cp)])
|
||||
(define-values (_ m p) (loop real-pos))
|
||||
(values (- (+ pos 3)) m p))]
|
||||
[(= pos -2)
|
||||
(values 0 (read-compact-number cp) (read-compact-number cp))]
|
||||
[else (values 0 0 pos)]))])
|
||||
(make-module-variable mod var pos mod-phase
|
||||
(cond
|
||||
[(not (zero? (bitwise-and #x1 flags))) 'constant]
|
||||
[(not (zero? (bitwise-and #x2 flags))) 'fixed]
|
||||
[else #f]))))]
|
||||
[(local-unbox)
|
||||
(let* ([p* (read-compact-number cp)]
|
||||
[p (if (< p* 0) (- (add1 p*)) p*)]
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
(define-form-struct module-variable ([modidx module-path-index?]
|
||||
[sym symbol?]
|
||||
[pos exact-integer?]
|
||||
[phase exact-nonnegative-integer?]))
|
||||
[phase exact-nonnegative-integer?]
|
||||
[constantness (or/c #f 'constant 'fixed)]))
|
||||
|
||||
;; Syntax object
|
||||
(define ((alist/c k? v?) l)
|
||||
|
|
|
@ -72,12 +72,19 @@ structures that are produced by @racket[zo-parse] and consumed by
|
|||
([modidx module-path-index?]
|
||||
[sym symbol?]
|
||||
[pos exact-integer?]
|
||||
[phase exact-nonnegative-integer?])]{
|
||||
[phase exact-nonnegative-integer?]
|
||||
[constantness (or/c #f 'constant 'fixed)])]{
|
||||
Represents a top-level variable, and used only in a @racket[prefix].
|
||||
The @racket[pos] may record the variable's offset within its module,
|
||||
or it can be @racket[-1] if the variable is always located by name.
|
||||
The @racket[phase] indicates the phase level of the definition within
|
||||
its module.}
|
||||
its module. The @racket[constantness] field is either @racket['constant]
|
||||
to indicate that
|
||||
variable's value is always the same for every instantiation of its module,
|
||||
@racket['fixed] to indicate
|
||||
that it doesn't change within a particular instantiation of the module,
|
||||
or @racket[#f] to indicate that the variable's value
|
||||
can change even for one particular instantiation of its module.}
|
||||
|
||||
|
||||
@defstruct+[(stx zo) ([encoded wrapped?])]{
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
(require racket/flonum
|
||||
racket/fixnum
|
||||
racket/unsafe/ops
|
||||
compiler/zo-parse)
|
||||
compiler/zo-parse
|
||||
compiler/zo-marshal)
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
@ -2219,5 +2220,65 @@
|
|||
(test #t (dynamic-require ''check-tail-call-by-jit-for-struct-predicate 'go))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Test bytecode validator's checking of constantness
|
||||
|
||||
(let ()
|
||||
(define c1
|
||||
'(module c1 racket/base
|
||||
(void ((if (zero? (random 1))
|
||||
(lambda (f) (displayln (f)))
|
||||
#f)
|
||||
(lambda ()
|
||||
;; This access of i should raise an exception:
|
||||
i)))
|
||||
(define i (random 1))))
|
||||
|
||||
(define o (open-output-bytes))
|
||||
|
||||
(parameterize ([current-namespace (make-base-namespace)])
|
||||
(write (compile c1) o))
|
||||
|
||||
(define m (zo-parse (open-input-bytes (get-output-bytes o))))
|
||||
|
||||
(define o2 (open-output-bytes))
|
||||
|
||||
;; construct bytecode that is broken by claiming that `i' is constant
|
||||
;; in the too-early reference:
|
||||
(void
|
||||
(write-bytes
|
||||
(zo-marshal
|
||||
(match m
|
||||
[(compilation-top max-let-depth prefix code)
|
||||
(compilation-top max-let-depth prefix
|
||||
(let ([body (mod-body code)])
|
||||
(struct-copy mod code [body
|
||||
(match body
|
||||
[(list a b)
|
||||
(list (match a
|
||||
[(application rator (list rand))
|
||||
(application
|
||||
rator
|
||||
(list
|
||||
(match rand
|
||||
[(application rator (list rand))
|
||||
(application
|
||||
rator
|
||||
(list
|
||||
(struct-copy
|
||||
lam rand
|
||||
[body
|
||||
(match (lam-body rand)
|
||||
[(toplevel depth pos const? ready?)
|
||||
(toplevel depth pos #t #t)])])))])))])
|
||||
b)])])))]))
|
||||
o2))
|
||||
|
||||
;; validator should reject this at read or eval time (depending on how lazy validation is):
|
||||
(err/rt-test (parameterize ([current-namespace (make-base-namespace)]
|
||||
[read-accept-compiled #t])
|
||||
(eval (read (open-input-bytes (get-output-bytes o2)))))
|
||||
exn:fail:read?))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(report-errs)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
Version 5.3.1.2
|
||||
compiler/zo-structs: added a constantness field to module-variable
|
||||
|
||||
Version 5.3.1.1
|
||||
Added arguments to impersonate-prompt-tag and chaperone-prompt-tag
|
||||
to support interposition on non-composable continuation results
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -787,7 +787,8 @@ static Scheme_Object *link_module_variable(Scheme_Object *modidx,
|
|||
int pos, int mod_phase,
|
||||
Scheme_Env *env,
|
||||
Scheme_Object **exprs, int which,
|
||||
char *import_map)
|
||||
char *import_map,
|
||||
int flags)
|
||||
{
|
||||
Scheme_Object *modname;
|
||||
Scheme_Env *menv;
|
||||
|
@ -840,14 +841,35 @@ static Scheme_Object *link_module_variable(Scheme_Object *modidx,
|
|||
|
||||
bkt = scheme_global_bucket(varname, menv);
|
||||
if (!self) {
|
||||
const char *bad_reason = NULL;
|
||||
|
||||
if (!bkt->val) {
|
||||
bad_reason = "uninitialized";
|
||||
} else if (flags) {
|
||||
if (flags & SCHEME_MODVAR_CONST) {
|
||||
/* The fact that the link target is consistent is a fine
|
||||
sanity check, but the check is not good enough for the JIT
|
||||
to rely on it. To be useful for the JIT, we'd have to make
|
||||
sure that every link goes to the same value. Since we can't
|
||||
currently guarantee that, all the JIT assumes is that the
|
||||
value is "fixed". */
|
||||
if (!(((Scheme_Bucket_With_Flags *)bkt)->flags & GLOB_IS_CONSISTENT))
|
||||
bad_reason = "not constant across all instantiations";
|
||||
} else {
|
||||
if (!(((Scheme_Bucket_With_Flags *)bkt)->flags & GLOB_IS_IMMUTATED))
|
||||
bad_reason = "not constant";
|
||||
}
|
||||
}
|
||||
|
||||
if (bad_reason) {
|
||||
scheme_wrong_syntax("link", NULL, varname,
|
||||
"bad variable linkage;\n"
|
||||
" reference to a variable that is uninitialized\n"
|
||||
" reference to a variable that is %s\n"
|
||||
" reference phase level: %d\n"
|
||||
" variable module: %D\n"
|
||||
" variable phase: %d\n"
|
||||
" reference in module: %D",
|
||||
bad_reason,
|
||||
env->phase,
|
||||
modname,
|
||||
mod_phase,
|
||||
|
@ -909,7 +931,8 @@ static Scheme_Object *link_toplevel(Scheme_Object **exprs, int which, Scheme_Env
|
|||
-1, mod_phase,
|
||||
env,
|
||||
NULL, 0,
|
||||
import_map);
|
||||
import_map,
|
||||
0);
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(expr), scheme_variable_type)) {
|
||||
Scheme_Bucket *b = (Scheme_Bucket *)expr;
|
||||
Scheme_Env *home;
|
||||
|
@ -925,7 +948,7 @@ static Scheme_Object *link_toplevel(Scheme_Object **exprs, int which, Scheme_Env
|
|||
-1, home->mod_phase,
|
||||
env,
|
||||
exprs, which,
|
||||
import_map);
|
||||
import_map, 0);
|
||||
} else {
|
||||
Module_Variable *mv = (Module_Variable *)expr;
|
||||
|
||||
|
@ -939,7 +962,8 @@ static Scheme_Object *link_toplevel(Scheme_Object **exprs, int which, Scheme_Env
|
|||
mv->pos, mv->mod_phase,
|
||||
env,
|
||||
exprs, which,
|
||||
import_map);
|
||||
import_map,
|
||||
SCHEME_MODVAR_FLAGS(mv) & 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1924,7 +1948,8 @@ define_execute_with_dynamic_state(Scheme_Object *vec, int delta, int defmacro,
|
|||
int flags = GLOB_IS_IMMUTATED;
|
||||
if (SCHEME_PROCP(vals_expr)
|
||||
|| SAME_TYPE(SCHEME_TYPE(vals_expr), scheme_unclosed_procedure_type)
|
||||
|| SAME_TYPE(SCHEME_TYPE(vals_expr), scheme_case_lambda_sequence_type))
|
||||
|| SAME_TYPE(SCHEME_TYPE(vals_expr), scheme_case_lambda_sequence_type)
|
||||
|| SAME_TYPE(SCHEME_TYPE(vals_expr), scheme_inline_variant_type))
|
||||
flags |= GLOB_IS_CONSISTENT;
|
||||
((Scheme_Bucket_With_Flags *)b)->flags |= flags;
|
||||
}
|
||||
|
@ -2401,6 +2426,10 @@ void scheme_delay_load_closure(Scheme_Closure_Data *data)
|
|||
(SCHEME_TRUEP(SCHEME_VEC_ELS(vinfo)[8])
|
||||
? (void *)SCHEME_VEC_ELS(vinfo)[8]
|
||||
: NULL),
|
||||
(SCHEME_TRUEP(SCHEME_VEC_ELS(vinfo)[9])
|
||||
? (mzshort *)(SCHEME_VEC_ELS(vinfo)[9])
|
||||
: NULL),
|
||||
SCHEME_INT_VAL(SCHEME_VEC_ELS(vinfo)[10]),
|
||||
SCHEME_INT_VAL(SCHEME_VEC_ELS(vinfo)[6]),
|
||||
(SCHEME_TRUEP(SCHEME_VEC_ELS(vinfo)[7])
|
||||
? (Scheme_Hash_Tree *)SCHEME_VEC_ELS(vinfo)[7]
|
||||
|
@ -4000,6 +4029,7 @@ static void *compile_k(void)
|
|||
top->prefix->num_stxes,
|
||||
top->prefix->num_lifts,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,24 @@ static void note_match(int actual, int expected, Optimize_Info *warn_info)
|
|||
}
|
||||
}
|
||||
|
||||
int scheme_is_functional_primitive(Scheme_Object *rator, int num_args, int expected_vals)
|
||||
/* return 2 => results are a constant when arguments are constants */
|
||||
{
|
||||
if (SCHEME_PRIMP(rator)
|
||||
&& (SCHEME_PRIM_PROC_FLAGS(rator) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_UNSAFE_NONMUTATING))
|
||||
&& (num_args >= ((Scheme_Primitive_Proc *)rator)->mina)
|
||||
&& (num_args <= ((Scheme_Primitive_Proc *)rator)->mu.maxa)
|
||||
&& ((expected_vals < 0)
|
||||
|| ((expected_vals == 1) && !(SCHEME_PRIM_PROC_FLAGS(rator) & SCHEME_PRIM_IS_MULTI_RESULT))
|
||||
|| (SAME_OBJ(scheme_values_func, rator)
|
||||
&& (expected_vals == num_args)))) {
|
||||
if (SAME_OBJ(scheme_values_func, rator))
|
||||
return 2;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
||||
Optimize_Info *warn_info, int deeper_than, int no_id)
|
||||
/* Checks whether the bytecode `o' returns `vals' values with no
|
||||
|
@ -373,13 +391,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
}
|
||||
|
||||
if (SCHEME_PRIMP(app->args[0])) {
|
||||
if ((SCHEME_PRIM_PROC_FLAGS(app->args[0]) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_UNSAFE_NONMUTATING))
|
||||
&& (app->num_args >= ((Scheme_Primitive_Proc *)app->args[0])->mina)
|
||||
&& (app->num_args <= ((Scheme_Primitive_Proc *)app->args[0])->mu.maxa)
|
||||
&& ((vals < 0)
|
||||
|| ((vals == 1) && !(SCHEME_PRIM_PROC_FLAGS(app->args[0]) & SCHEME_PRIM_IS_MULTI_RESULT))
|
||||
|| (SAME_OBJ(scheme_values_func, app->args[0])
|
||||
&& (vals == app->num_args)))) {
|
||||
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,
|
||||
|
@ -400,12 +412,7 @@ 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_PRIM_PROC_FLAGS(app->rator) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_UNSAFE_NONMUTATING))
|
||||
&& (1 >= ((Scheme_Primitive_Proc *)app->rator)->mina)
|
||||
&& (1 <= ((Scheme_Primitive_Proc *)app->rator)->mu.maxa)
|
||||
&& ((vals < 0)
|
||||
|| ((vals == 1) && !(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT))
|
||||
|| ((vals == 1) && SAME_OBJ(scheme_values_func, 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;
|
||||
|
@ -420,12 +427,7 @@ 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_PRIM_PROC_FLAGS(app->rator) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_UNSAFE_NONMUTATING))
|
||||
&& (2 >= ((Scheme_Primitive_Proc *)app->rator)->mina)
|
||||
&& (2 <= ((Scheme_Primitive_Proc *)app->rator)->mu.maxa)
|
||||
&& ((vals < 0)
|
||||
|| ((vals == 1) && !(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT))
|
||||
|| ((vals == 2) && SAME_OBJ(scheme_values_func, 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,
|
||||
|
@ -1800,7 +1802,7 @@ static Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *r
|
|||
c = SCHEME_BOX_VAL(c);
|
||||
|
||||
while (SAME_TYPE(SCHEME_TYPE(c), scheme_compiled_let_void_type)) {
|
||||
/* This must be (let ([x <proc>]) <proc>); see scheme_is_statically_proc() */
|
||||
/* This must be (let ([x <omittable>]) <proc>); see scheme_is_statically_proc() */
|
||||
Scheme_Let_Header *lh = (Scheme_Let_Header *)c;
|
||||
Scheme_Compiled_Let_Value *lv = (Scheme_Compiled_Let_Value *)lh->body;
|
||||
c = lv->body;
|
||||
|
@ -3095,7 +3097,7 @@ int scheme_is_statically_proc(Scheme_Object *value, Optimize_Info *info)
|
|||
else if (SAME_TYPE(SCHEME_TYPE(value), scheme_case_lambda_sequence_type)) {
|
||||
return 1;
|
||||
} else if (SAME_TYPE(SCHEME_TYPE(value), scheme_compiled_let_void_type)) {
|
||||
/* Look for (let ([x <proc>]) <proc>), which is generated for optional arguments. */
|
||||
/* Look for (let ([x <omittable>]) <proc>), which is generated for optional arguments. */
|
||||
Scheme_Let_Header *lh = (Scheme_Let_Header *)value;
|
||||
if (lh->num_clauses == 1) {
|
||||
Scheme_Compiled_Let_Value *lv = (Scheme_Compiled_Let_Value *)lh->body;
|
||||
|
|
|
@ -2885,10 +2885,10 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht,
|
|||
if (idx) {
|
||||
print_symtab_ref(pp, idx);
|
||||
} else {
|
||||
Module_Variable *mv;
|
||||
Module_Variable *mv = (Module_Variable *)obj;
|
||||
int flags = SCHEME_MODVAR_FLAGS(mv);
|
||||
|
||||
print_compact(pp, CPT_MODULE_VAR);
|
||||
mv = (Module_Variable *)obj;
|
||||
if (SAME_TYPE(SCHEME_TYPE(mv->modidx), scheme_resolved_module_path_type)
|
||||
&& SCHEME_SYMBOLP(SCHEME_PTR_VAL(mv->modidx))) {
|
||||
print(SCHEME_PTR_VAL(mv->modidx), notdisplay, 1, ht, mt, pp);
|
||||
|
@ -2896,6 +2896,9 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht,
|
|||
print(mv->modidx, notdisplay, 1, ht, mt, pp);
|
||||
}
|
||||
print(mv->sym, notdisplay, 1, ht, mt, pp);
|
||||
if (flags & 0x3) {
|
||||
print_compact_number(pp, -3-(flags&0x3));
|
||||
}
|
||||
if (((Module_Variable *)obj)->mod_phase) {
|
||||
print_compact_number(pp, -2);
|
||||
print_compact_number(pp, mv->mod_phase);
|
||||
|
|
|
@ -4705,6 +4705,11 @@ static Scheme_Object *read_compact(CPort *port, int use_stack)
|
|||
mod = scheme_intern_resolved_module_path(mod);
|
||||
mv->modidx = mod;
|
||||
mv->sym = var;
|
||||
if (pos < -3) {
|
||||
pos = -(pos + 3);
|
||||
SCHEME_MODVAR_FLAGS(mv) = pos;
|
||||
pos = read_compact_number(port);
|
||||
}
|
||||
if (pos == -2) {
|
||||
pos = read_compact_number(port);
|
||||
mv->mod_phase = pos;
|
||||
|
@ -5366,6 +5371,7 @@ static Scheme_Object *read_compiled(Scheme_Object *port,
|
|||
top->prefix->num_stxes,
|
||||
top->prefix->num_lifts,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
/* If no exception, the resulting code is ok. */
|
||||
|
||||
|
|
|
@ -2239,7 +2239,7 @@ static Scheme_Object *
|
|||
module_expr_resolve(Scheme_Object *data, Resolve_Info *old_rslv)
|
||||
{
|
||||
Scheme_Module *m = (Scheme_Module *)data;
|
||||
Scheme_Object *b, *lift_vec;
|
||||
Scheme_Object *b, *lift_vec, *body = scheme_null;
|
||||
Resolve_Prefix *rp;
|
||||
Resolve_Info *rslv;
|
||||
int i, cnt;
|
||||
|
@ -2264,19 +2264,27 @@ module_expr_resolve(Scheme_Object *data, Resolve_Info *old_rslv)
|
|||
for (i = 0; i < cnt; i++) {
|
||||
Scheme_Object *e;
|
||||
e = scheme_resolve_expr(SCHEME_VEC_ELS(m->bodies[0])[i], rslv);
|
||||
SCHEME_VEC_ELS(m->bodies[0])[i] = e;
|
||||
|
||||
/* add lift just before the expression that introduced it;
|
||||
this ordering is needed for bytecode validation of
|
||||
constantness for top-level references */
|
||||
lift_vec = rslv->lifts;
|
||||
if (!SCHEME_NULLP(SCHEME_VEC_ELS(lift_vec)[0])) {
|
||||
body = scheme_append(SCHEME_VEC_ELS(lift_vec)[0], body);
|
||||
SCHEME_VEC_ELS(lift_vec)[0] = scheme_null;
|
||||
}
|
||||
|
||||
body = scheme_make_pair(e, body);
|
||||
}
|
||||
|
||||
m->max_let_depth = rslv->max_let_depth;
|
||||
|
||||
lift_vec = rslv->lifts;
|
||||
if (!SCHEME_NULLP(SCHEME_VEC_ELS(lift_vec)[0])) {
|
||||
b = scheme_append(SCHEME_VEC_ELS(lift_vec)[0], scheme_vector_to_list(m->bodies[0]));
|
||||
b = scheme_list_to_vector(b);
|
||||
m->bodies[0] = b;
|
||||
}
|
||||
rp->num_lifts = SCHEME_INT_VAL(SCHEME_VEC_ELS(lift_vec)[1]);
|
||||
|
||||
body = scheme_list_to_vector(scheme_reverse(body));
|
||||
m->bodies[0] = body;
|
||||
|
||||
rp = scheme_remap_prefix(rp, rslv);
|
||||
|
||||
m->prefix = rp;
|
||||
|
|
|
@ -2346,21 +2346,6 @@ typedef struct Scheme_Object *
|
|||
|
||||
typedef struct CPort Mz_CPort;
|
||||
|
||||
typedef mzshort **Validate_TLS;
|
||||
struct Validate_Clearing;
|
||||
|
||||
typedef void (*Scheme_Syntax_Validater)(Scheme_Object *data, Mz_CPort *port,
|
||||
char *stack, Validate_TLS tls,
|
||||
int depth, int letlimit, int delta,
|
||||
int num_toplevels, int num_stxes, int num_lifts,
|
||||
void *tl_use_map, int result_ignored,
|
||||
struct Validate_Clearing *vc, int tailpos,
|
||||
Scheme_Hash_Tree *procs);
|
||||
|
||||
typedef struct Scheme_Object *(*Scheme_Syntax_Executer)(struct Scheme_Object *data);
|
||||
|
||||
typedef struct Scheme_Object *(*Scheme_Syntax_Jitter)(struct Scheme_Object *data);
|
||||
|
||||
typedef struct Scheme_Closure_Data
|
||||
{
|
||||
Scheme_Inclhash_Object iso; /* keyex used for flags */
|
||||
|
@ -2883,6 +2868,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved,
|
|||
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_env_variable_boxed(Scheme_Comp_Env *env, int which);
|
||||
|
||||
|
@ -2922,23 +2908,16 @@ Scheme_Env *scheme_environment_from_dummy(Scheme_Object *dummy);
|
|||
void scheme_validate_code(Mz_CPort *port, Scheme_Object *code,
|
||||
int depth,
|
||||
int num_toplevels, int num_stxes, int num_lifts, void *tl_use_map,
|
||||
Scheme_Object **toplevels,
|
||||
int code_vec);
|
||||
void scheme_validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
||||
char *stack, Validate_TLS tls,
|
||||
int depth, int letlimit, int delta,
|
||||
int num_toplevels, int num_stxes, int num_lifts, void *tl_use_map,
|
||||
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 scheme_validate_rator_wants_box(Scheme_Object *app_rator, int pos,
|
||||
int hope,
|
||||
Validate_TLS tls,
|
||||
int num_toplevels, int num_stxes, int num_lifts, void *tl_use_map);
|
||||
typedef mzshort **Validate_TLS;
|
||||
struct Validate_Clearing;
|
||||
|
||||
void scheme_validate_closure(Mz_CPort *port, Scheme_Object *expr,
|
||||
char *new_stack, Validate_TLS tls,
|
||||
char *closure_stack, Validate_TLS tls,
|
||||
int num_toplevels, int num_stxes, int num_lifts, void *tl_use_map,
|
||||
mzshort *tl_state, mzshort tl_timestamp,
|
||||
int self_pos_in_closure, Scheme_Hash_Tree *procs);
|
||||
|
||||
#define TRACK_ILL_FORMED_CATCH_LINES 1
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
consistently.)
|
||||
*/
|
||||
|
||||
#define MZSCHEME_VERSION "5.3.1.1"
|
||||
#define MZSCHEME_VERSION "5.3.1.2"
|
||||
|
||||
#define MZSCHEME_VERSION_X 5
|
||||
#define MZSCHEME_VERSION_Y 3
|
||||
#define MZSCHEME_VERSION_Z 1
|
||||
#define MZSCHEME_VERSION_W 1
|
||||
#define MZSCHEME_VERSION_W 2
|
||||
|
||||
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
||||
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user